"no use strict";;
(function(window) {
    if (typeof window.window != "undefined" && window.document)
        return;
    if (window.require && window.define)
        return;

    if (!window.console) {
        window.console = function() {
            var msgs = Array.prototype.slice.call(arguments, 0);
            postMessage({
                type: "log",
                data: msgs
            });
        };
        window.console.error =
            window.console.warn =
            window.console.log =
            window.console.trace = window.console;
    }
    window.window = window;
    window.ace = window;

    window.onerror = function(message, file, line, col, err) {
        postMessage({
            type: "error",
            data: {
                message: message,
                data: err.data,
                file: file,
                line: line,
                col: col,
                stack: err.stack
            }
        });
    };

    window.normalizeModule = function(parentId, moduleName) {
        // normalize plugin requires
        if (moduleName.indexOf("!") !== -1) {
            var chunks = moduleName.split("!");
            return window.normalizeModule(parentId, chunks[0]) + "!" + window.normalizeModule(parentId, chunks[1]);
        }
        // normalize relative requires
        if (moduleName.charAt(0) == ".") {
            var base = parentId.split("/").slice(0, -1).join("/");
            moduleName = (base ? base + "/" : "") + moduleName;

            while (moduleName.indexOf(".") !== -1 && previous != moduleName) {
                var previous = moduleName;
                moduleName = moduleName.replace(/^\.\//, "").replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, "");
            }
        }

        return moduleName;
    };

    window.require = function require(parentId, id) {
        if (!id) {
            id = parentId;
            parentId = null;
        }
        if (!id.charAt)
            throw new Error("worker.js require() accepts only (parentId, id) as arguments");

        id = window.normalizeModule(parentId, id);

        var module = window.require.modules[id];
        if (module) {
            if (!module.initialized) {
                module.initialized = true;
                module.exports = module.factory().exports;
            }
            return module.exports;
        }

        if (!window.require.tlns)
            return console.log("unable to load " + id);

        var path = resolveModuleId(id, window.require.tlns);
        if (path.slice(-3) != ".js") path += ".js";

        window.require.id = id;
        window.require.modules[id] = {}; // prevent infinite loop on broken modules
        importScripts(path);
        return window.require(parentId, id);
    };

    function resolveModuleId(id, paths) {
        var testPath = id,
            tail = "";
        while (testPath) {
            var alias = paths[testPath];
            if (typeof alias == "string") {
                return alias + tail;
            } else if (alias) {
                return alias.location.replace(/\/*$/, "/") + (tail || alias.main || alias.name);
            } else if (alias === false) {
                return "";
            }
            var i = testPath.lastIndexOf("/");
            if (i === -1) break;
            tail = testPath.substr(i) + tail;
            testPath = testPath.slice(0, i);
        }
        return id;
    }
    window.require.modules = {};
    window.require.tlns = {};

    window.define = function(id, deps, factory) {
        if (arguments.length == 2) {
            factory = deps;
            if (typeof id != "string") {
                deps = id;
                id = window.require.id;
            }
        } else if (arguments.length == 1) {
            factory = id;
            deps = [];
            id = window.require.id;
        }

        if (typeof factory != "function") {
            window.require.modules[id] = {
                exports: factory,
                initialized: true
            };
            return;
        }

        if (!deps.length)
        // If there is no dependencies, we inject "require", "exports" and
        // "module" as dependencies, to provide CommonJS compatibility.
            deps = ["require", "exports", "module"];

        var req = function(childId) {
            return window.require(id, childId);
        };

        window.require.modules[id] = {
            exports: {},
            factory: function() {
                var module = this;
                var returnExports = factory.apply(this, deps.map(function(dep) {
                    switch (dep) {
                        // Because "require", "exports" and "module" aren't actual
                        // dependencies, we must handle them seperately.
                        case "require":
                            return req;
                        case "exports":
                            return module.exports;
                        case "module":
                            return module;
                            // But for all other dependencies, we can just go ahead and
                            // require them.
                        default:
                            return req(dep);
                    }
                }));
                if (returnExports)
                    module.exports = returnExports;
                return module;
            }
        };
    };
    window.define.amd = {};
    require.tlns = {};
    window.initBaseUrls = function initBaseUrls(topLevelNamespaces) {
        for (var i in topLevelNamespaces)
            require.tlns[i] = topLevelNamespaces[i];
    };

    window.initSender = function initSender() {

        var EventEmitter = window.require("ace/lib/event_emitter").EventEmitter;
        var oop = window.require("ace/lib/oop");

        var Sender = function() {};

        (function() {

            oop.implement(this, EventEmitter);

            this.callback = function(data, callbackId) {
                postMessage({
                    type: "call",
                    id: callbackId,
                    data: data
                });
            };

            this.emit = function(name, data) {
                postMessage({
                    type: "event",
                    name: name,
                    data: data
                });
            };

        }).call(Sender.prototype);

        return new Sender();
    };

    var main = window.main = null;
    var sender = window.sender = null;

    window.onmessage = function(e) {
        var msg = e.data;
        if (msg.event && sender) {
            sender._signal(msg.event, msg.data);
        } else if (msg.command) {
            if (main[msg.command])
                main[msg.command].apply(main, msg.args);
            else if (window[msg.command])
                window[msg.command].apply(window, msg.args);
            else
                throw new Error("Unknown command:" + msg.command);
        } else if (msg.init) {
            window.initBaseUrls(msg.tlns);
            require("ace/lib/es5-shim");
            sender = window.sender = window.initSender();
            var clazz = require(msg.module)[msg.classname];
            main = window.main = new clazz(sender);
        }
    };
})(this);

define("ace/lib/oop", ["require", "exports", "module"], function(require, exports, module) {
    "use strict";

    exports.inherits = function(ctor, superCtor) {
        ctor.super_ = superCtor;
        ctor.prototype = Object.create(superCtor.prototype, {
            constructor: {
                value: ctor,
                enumerable: false,
                writable: true,
                configurable: true
            }
        });
    };

    exports.mixin = function(obj, mixin) {
        for (var key in mixin) {
            obj[key] = mixin[key];
        }
        return obj;
    };

    exports.implement = function(proto, mixin) {
        exports.mixin(proto, mixin);
    };

});

define("ace/range", ["require", "exports", "module"], function(require, exports, module) {
    "use strict";
    var comparePoints = function(p1, p2) {
        return p1.row - p2.row || p1.column - p2.column;
    };
    var Range = function(startRow, startColumn, endRow, endColumn) {
        this.start = {
            row: startRow,
            column: startColumn
        };

        this.end = {
            row: endRow,
            column: endColumn
        };
    };

    (function() {
        this.isEqual = function(range) {
            return this.start.row === range.start.row &&
                this.end.row === range.end.row &&
                this.start.column === range.start.column &&
                this.end.column === range.end.column;
        };
        this.toString = function() {
            return ("Range: [" + this.start.row + "/" + this.start.column +
                "] -> [" + this.end.row + "/" + this.end.column + "]");
        };

        this.contains = function(row, column) {
            return this.compare(row, column) == 0;
        };
        this.compareRange = function(range) {
            var cmp,
                end = range.end,
                start = range.start;

            cmp = this.compare(end.row, end.column);
            if (cmp == 1) {
                cmp = this.compare(start.row, start.column);
                if (cmp == 1) {
                    return 2;
                } else if (cmp == 0) {
                    return 1;
                } else {
                    return 0;
                }
            } else if (cmp == -1) {
                return -2;
            } else {
                cmp = this.compare(start.row, start.column);
                if (cmp == -1) {
                    return -1;
                } else if (cmp == 1) {
                    return 42;
                } else {
                    return 0;
                }
            }
        };
        this.comparePoint = function(p) {
            return this.compare(p.row, p.column);
        };
        this.containsRange = function(range) {
            return this.comparePoint(range.start) == 0 && this.comparePoint(range.end) == 0;
        };
        this.intersects = function(range) {
            var cmp = this.compareRange(range);
            return (cmp == -1 || cmp == 0 || cmp == 1);
        };
        this.isEnd = function(row, column) {
            return this.end.row == row && this.end.column == column;
        };
        this.isStart = function(row, column) {
            return this.start.row == row && this.start.column == column;
        };
        this.setStart = function(row, column) {
            if (typeof row == "object") {
                this.start.column = row.column;
                this.start.row = row.row;
            } else {
                this.start.row = row;
                this.start.column = column;
            }
        };
        this.setEnd = function(row, column) {
            if (typeof row == "object") {
                this.end.column = row.column;
                this.end.row = row.row;
            } else {
                this.end.row = row;
                this.end.column = column;
            }
        };
        this.inside = function(row, column) {
            if (this.compare(row, column) == 0) {
                if (this.isEnd(row, column) || this.isStart(row, column)) {
                    return false;
                } else {
                    return true;
                }
            }
            return false;
        };
        this.insideStart = function(row, column) {
            if (this.compare(row, column) == 0) {
                if (this.isEnd(row, column)) {
                    return false;
                } else {
                    return true;
                }
            }
            return false;
        };
        this.insideEnd = function(row, column) {
            if (this.compare(row, column) == 0) {
                if (this.isStart(row, column)) {
                    return false;
                } else {
                    return true;
                }
            }
            return false;
        };
        this.compare = function(row, column) {
            if (!this.isMultiLine()) {
                if (row === this.start.row) {
                    return column < this.start.column ? -1 : (column > this.end.column ? 1 : 0);
                }
            }

            if (row < this.start.row)
                return -1;

            if (row > this.end.row)
                return 1;

            if (this.start.row === row)
                return column >= this.start.column ? 0 : -1;

            if (this.end.row === row)
                return column <= this.end.column ? 0 : 1;

            return 0;
        };
        this.compareStart = function(row, column) {
            if (this.start.row == row && this.start.column == column) {
                return -1;
            } else {
                return this.compare(row, column);
            }
        };
        this.compareEnd = function(row, column) {
            if (this.end.row == row && this.end.column == column) {
                return 1;
            } else {
                return this.compare(row, column);
            }
        };
        this.compareInside = function(row, column) {
            if (this.end.row == row && this.end.column == column) {
                return 1;
            } else if (this.start.row == row && this.start.column == column) {
                return -1;
            } else {
                return this.compare(row, column);
            }
        };
        this.clipRows = function(firstRow, lastRow) {
            if (this.end.row > lastRow)
                var end = {
                    row: lastRow + 1,
                    column: 0
                };
            else if (this.end.row < firstRow)
                var end = {
                    row: firstRow,
                    column: 0
                };

            if (this.start.row > lastRow)
                var start = {
                    row: lastRow + 1,
                    column: 0
                };
            else if (this.start.row < firstRow)
                var start = {
                    row: firstRow,
                    column: 0
                };

            return Range.fromPoints(start || this.start, end || this.end);
        };
        this.extend = function(row, column) {
            var cmp = this.compare(row, column);

            if (cmp == 0)
                return this;
            else if (cmp == -1)
                var start = {
                    row: row,
                    column: column
                };
            else
                var end = {
                    row: row,
                    column: column
                };

            return Range.fromPoints(start || this.start, end || this.end);
        };

        this.isEmpty = function() {
            return (this.start.row === this.end.row && this.start.column === this.end.column);
        };
        this.isMultiLine = function() {
            return (this.start.row !== this.end.row);
        };
        this.clone = function() {
            return Range.fromPoints(this.start, this.end);
        };
        this.collapseRows = function() {
            if (this.end.column == 0)
                return new Range(this.start.row, 0, Math.max(this.start.row, this.end.row - 1), 0)
            else
                return new Range(this.start.row, 0, this.end.row, 0)
        };
        this.toScreenRange = function(session) {
            var screenPosStart = session.documentToScreenPosition(this.start);
            var screenPosEnd = session.documentToScreenPosition(this.end);

            return new Range(
                screenPosStart.row, screenPosStart.column,
                screenPosEnd.row, screenPosEnd.column
            );
        };
        this.moveBy = function(row, column) {
            this.start.row += row;
            this.start.column += column;
            this.end.row += row;
            this.end.column += column;
        };

    }).call(Range.prototype);
    Range.fromPoints = function(start, end) {
        return new Range(start.row, start.column, end.row, end.column);
    };
    Range.comparePoints = comparePoints;

    Range.comparePoints = function(p1, p2) {
        return p1.row - p2.row || p1.column - p2.column;
    };


    exports.Range = Range;
});

define("ace/apply_delta", ["require", "exports", "module"], function(require, exports, module) {
    "use strict";

    function throwDeltaError(delta, errorText) {
        console.log("Invalid Delta:", delta);
        throw "Invalid Delta: " + errorText;
    }

    function positionInDocument(docLines, position) {
        return position.row >= 0 && position.row < docLines.length &&
            position.column >= 0 && position.column <= docLines[position.row].length;
    }

    function validateDelta(docLines, delta) {
        if (delta.action != "insert" && delta.action != "remove")
            throwDeltaError(delta, "delta.action must be 'insert' or 'remove'");
        if (!(delta.lines instanceof Array))
            throwDeltaError(delta, "delta.lines must be an Array");
        if (!delta.start || !delta.end)
            throwDeltaError(delta, "delta.start/end must be an present");
        var start = delta.start;
        if (!positionInDocument(docLines, delta.start))
            throwDeltaError(delta, "delta.start must be contained in document");
        var end = delta.end;
        if (delta.action == "remove" && !positionInDocument(docLines, end))
            throwDeltaError(delta, "delta.end must contained in document for 'remove' actions");
        var numRangeRows = end.row - start.row;
        var numRangeLastLineChars = (end.column - (numRangeRows == 0 ? start.column : 0));
        if (numRangeRows != delta.lines.length - 1 || delta.lines[numRangeRows].length != numRangeLastLineChars)
            throwDeltaError(delta, "delta.range must match delta lines");
    }

    exports.applyDelta = function(docLines, delta, doNotValidate) {

        var row = delta.start.row;
        var startColumn = delta.start.column;
        var line = docLines[row] || "";
        switch (delta.action) {
            case "insert":
                var lines = delta.lines;
                if (lines.length === 1) {
                    docLines[row] = line.substring(0, startColumn) + delta.lines[0] + line.substring(startColumn);
                } else {
                    var args = [row, 1].concat(delta.lines);
                    docLines.splice.apply(docLines, args);
                    docLines[row] = line.substring(0, startColumn) + docLines[row];
                    docLines[row + delta.lines.length - 1] += line.substring(startColumn);
                }
                break;
            case "remove":
                var endColumn = delta.end.column;
                var endRow = delta.end.row;
                if (row === endRow) {
                    docLines[row] = line.substring(0, startColumn) + line.substring(endColumn);
                } else {
                    docLines.splice(
                        row, endRow - row + 1,
                        line.substring(0, startColumn) + docLines[endRow].substring(endColumn)
                    );
                }
                break;
        }
    }
});

define("ace/lib/event_emitter", ["require", "exports", "module"], function(require, exports, module) {
    "use strict";

    var EventEmitter = {};
    var stopPropagation = function() {
        this.propagationStopped = true;
    };
    var preventDefault = function() {
        this.defaultPrevented = true;
    };

    EventEmitter._emit =
        EventEmitter._dispatchEvent = function(eventName, e) {
            this._eventRegistry || (this._eventRegistry = {});
            this._defaultHandlers || (this._defaultHandlers = {});

            var listeners = this._eventRegistry[eventName] || [];
            var defaultHandler = this._defaultHandlers[eventName];
            if (!listeners.length && !defaultHandler)
                return;

            if (typeof e != "object" || !e)
                e = {};

            if (!e.type)
                e.type = eventName;
            if (!e.stopPropagation)
                e.stopPropagation = stopPropagation;
            if (!e.preventDefault)
                e.preventDefault = preventDefault;

            listeners = listeners.slice();
            for (var i = 0; i < listeners.length; i++) {
                listeners[i](e, this);
                if (e.propagationStopped)
                    break;
            }

            if (defaultHandler && !e.defaultPrevented)
                return defaultHandler(e, this);
        };


    EventEmitter._signal = function(eventName, e) {
        var listeners = (this._eventRegistry || {})[eventName];
        if (!listeners)
            return;
        listeners = listeners.slice();
        for (var i = 0; i < listeners.length; i++)
            listeners[i](e, this);
    };

    EventEmitter.once = function(eventName, callback) {
        var _self = this;
        callback && this.addEventListener(eventName, function newCallback() {
            _self.removeEventListener(eventName, newCallback);
            callback.apply(null, arguments);
        });
    };


    EventEmitter.setDefaultHandler = function(eventName, callback) {
        var handlers = this._defaultHandlers
        if (!handlers)
            handlers = this._defaultHandlers = {
                _disabled_: {}
            };

        if (handlers[eventName]) {
            var old = handlers[eventName];
            var disabled = handlers._disabled_[eventName];
            if (!disabled)
                handlers._disabled_[eventName] = disabled = [];
            disabled.push(old);
            var i = disabled.indexOf(callback);
            if (i != -1)
                disabled.splice(i, 1);
        }
        handlers[eventName] = callback;
    };
    EventEmitter.removeDefaultHandler = function(eventName, callback) {
        var handlers = this._defaultHandlers
        if (!handlers)
            return;
        var disabled = handlers._disabled_[eventName];

        if (handlers[eventName] == callback) {
            var old = handlers[eventName];
            if (disabled)
                this.setDefaultHandler(eventName, disabled.pop());
        } else if (disabled) {
            var i = disabled.indexOf(callback);
            if (i != -1)
                disabled.splice(i, 1);
        }
    };

    EventEmitter.on =
        EventEmitter.addEventListener = function(eventName, callback, capturing) {
            this._eventRegistry = this._eventRegistry || {};

            var listeners = this._eventRegistry[eventName];
            if (!listeners)
                listeners = this._eventRegistry[eventName] = [];

            if (listeners.indexOf(callback) == -1)
                listeners[capturing ? "unshift" : "push"](callback);
            return callback;
        };

    EventEmitter.off =
        EventEmitter.removeListener =
        EventEmitter.removeEventListener = function(eventName, callback) {
            this._eventRegistry = this._eventRegistry || {};

            var listeners = this._eventRegistry[eventName];
            if (!listeners)
                return;

            var index = listeners.indexOf(callback);
            if (index !== -1)
                listeners.splice(index, 1);
        };

    EventEmitter.removeAllListeners = function(eventName) {
        if (this._eventRegistry) this._eventRegistry[eventName] = [];
    };

    exports.EventEmitter = EventEmitter;

});

define("ace/anchor", ["require", "exports", "module", "ace/lib/oop", "ace/lib/event_emitter"], function(require, exports, module) {
    "use strict";

    var oop = require("./lib/oop");
    var EventEmitter = require("./lib/event_emitter").EventEmitter;

    var Anchor = exports.Anchor = function(doc, row, column) {
        this.$onChange = this.onChange.bind(this);
        this.attach(doc);

        if (typeof column == "undefined")
            this.setPosition(row.row, row.column);
        else
            this.setPosition(row, column);
    };

    (function() {

        oop.implement(this, EventEmitter);
        this.getPosition = function() {
            return this.$clipPositionToDocument(this.row, this.column);
        };
        this.getDocument = function() {
            return this.document;
        };
        this.$insertRight = false;
        this.onChange = function(delta) {
            if (delta.start.row == delta.end.row && delta.start.row != this.row)
                return;

            if (delta.start.row > this.row)
                return;

            var point = $getTransformedPoint(delta, {
                row: this.row,
                column: this.column
            }, this.$insertRight);
            this.setPosition(point.row, point.column, true);
        };

        function $pointsInOrder(point1, point2, equalPointsInOrder) {
            var bColIsAfter = equalPointsInOrder ? point1.column <= point2.column : point1.column < point2.column;
            return (point1.row < point2.row) || (point1.row == point2.row && bColIsAfter);
        }

        function $getTransformedPoint(delta, point, moveIfEqual) {
            var deltaIsInsert = delta.action == "insert";
            var deltaRowShift = (deltaIsInsert ? 1 : -1) * (delta.end.row - delta.start.row);
            var deltaColShift = (deltaIsInsert ? 1 : -1) * (delta.end.column - delta.start.column);
            var deltaStart = delta.start;
            var deltaEnd = deltaIsInsert ? deltaStart : delta.end; // Collapse insert range.
            if ($pointsInOrder(point, deltaStart, moveIfEqual)) {
                return {
                    row: point.row,
                    column: point.column
                };
            }
            if ($pointsInOrder(deltaEnd, point, !moveIfEqual)) {
                return {
                    row: point.row + deltaRowShift,
                    column: point.column + (point.row == deltaEnd.row ? deltaColShift : 0)
                };
            }

            return {
                row: deltaStart.row,
                column: deltaStart.column
            };
        }
        this.setPosition = function(row, column, noClip) {
            var pos;
            if (noClip) {
                pos = {
                    row: row,
                    column: column
                };
            } else {
                pos = this.$clipPositionToDocument(row, column);
            }

            if (this.row == pos.row && this.column == pos.column)
                return;

            var old = {
                row: this.row,
                column: this.column
            };

            this.row = pos.row;
            this.column = pos.column;
            this._signal("change", {
                old: old,
                value: pos
            });
        };
        this.detach = function() {
            this.document.removeEventListener("change", this.$onChange);
        };
        this.attach = function(doc) {
            this.document = doc || this.document;
            this.document.on("change", this.$onChange);
        };
        this.$clipPositionToDocument = function(row, column) {
            var pos = {};

            if (row >= this.document.getLength()) {
                pos.row = Math.max(0, this.document.getLength() - 1);
                pos.column = this.document.getLine(pos.row).length;
            } else if (row < 0) {
                pos.row = 0;
                pos.column = 0;
            } else {
                pos.row = row;
                pos.column = Math.min(this.document.getLine(pos.row).length, Math.max(0, column));
            }

            if (column < 0)
                pos.column = 0;

            return pos;
        };

    }).call(Anchor.prototype);

});

define("ace/document", ["require", "exports", "module", "ace/lib/oop", "ace/apply_delta", "ace/lib/event_emitter", "ace/range", "ace/anchor"], function(require, exports, module) {
    "use strict";

    var oop = require("./lib/oop");
    var applyDelta = require("./apply_delta").applyDelta;
    var EventEmitter = require("./lib/event_emitter").EventEmitter;
    var Range = require("./range").Range;
    var Anchor = require("./anchor").Anchor;

    var Document = function(textOrLines) {
        this.$lines = [""];
        if (textOrLines.length === 0) {
            this.$lines = [""];
        } else if (Array.isArray(textOrLines)) {
            this.insertMergedLines({
                row: 0,
                column: 0
            }, textOrLines);
        } else {
            this.insert({
                row: 0,
                column: 0
            }, textOrLines);
        }
    };

    (function() {

        oop.implement(this, EventEmitter);
        this.setValue = function(text) {
            var len = this.getLength() - 1;
            this.remove(new Range(0, 0, len, this.getLine(len).length));
            this.insert({
                row: 0,
                column: 0
            }, text);
        };
        this.getValue = function() {
            return this.getAllLines().join(this.getNewLineCharacter());
        };
        this.createAnchor = function(row, column) {
            return new Anchor(this, row, column);
        };
        if ("aaa".split(/a/).length === 0) {
            this.$split = function(text) {
                return text.replace(/\r\n|\r/g, "\n").split("\n");
            };
        } else {
            this.$split = function(text) {
                return text.split(/\r\n|\r|\n/);
            };
        }


        this.$detectNewLine = function(text) {
            var match = text.match(/^.*?(\r\n|\r|\n)/m);
            this.$autoNewLine = match ? match[1] : "\n";
            this._signal("changeNewLineMode");
        };
        this.getNewLineCharacter = function() {
            switch (this.$newLineMode) {
                case "windows":
                    return "\r\n";
                case "unix":
                    return "\n";
                default:
                    return this.$autoNewLine || "\n";
            }
        };

        this.$autoNewLine = "";
        this.$newLineMode = "auto";
        this.setNewLineMode = function(newLineMode) {
            if (this.$newLineMode === newLineMode)
                return;

            this.$newLineMode = newLineMode;
            this._signal("changeNewLineMode");
        };
        this.getNewLineMode = function() {
            return this.$newLineMode;
        };
        this.isNewLine = function(text) {
            return (text == "\r\n" || text == "\r" || text == "\n");
        };
        this.getLine = function(row) {
            return this.$lines[row] || "";
        };
        this.getLines = function(firstRow, lastRow) {
            return this.$lines.slice(firstRow, lastRow + 1);
        };
        this.getAllLines = function() {
            return this.getLines(0, this.getLength());
        };
        this.getLength = function() {
            return this.$lines.length;
        };
        this.getTextRange = function(range) {
            return this.getLinesForRange(range).join(this.getNewLineCharacter());
        };
        this.getLinesForRange = function(range) {
            var lines;
            if (range.start.row === range.end.row) {
                lines = [this.getLine(range.start.row).substring(range.start.column, range.end.column)];
            } else {
                lines = this.getLines(range.start.row, range.end.row);
                lines[0] = (lines[0] || "").substring(range.start.column);
                var l = lines.length - 1;
                if (range.end.row - range.start.row == l)
                    lines[l] = lines[l].substring(0, range.end.column);
            }
            return lines;
        };
        this.insertLines = function(row, lines) {
            console.warn("Use of document.insertLines is deprecated. Use the insertFullLines method instead.");
            return this.insertFullLines(row, lines);
        };
        this.removeLines = function(firstRow, lastRow) {
            console.warn("Use of document.removeLines is deprecated. Use the removeFullLines method instead.");
            return this.removeFullLines(firstRow, lastRow);
        };
        this.insertNewLine = function(position) {
            console.warn("Use of document.insertNewLine is deprecated. Use insertMergedLines(position, ['', '']) instead.");
            return this.insertMergedLines(position, ["", ""]);
        };
        this.insert = function(position, text) {
            if (this.getLength() <= 1)
                this.$detectNewLine(text);

            return this.insertMergedLines(position, this.$split(text));
        };
        this.insertInLine = function(position, text) {
            var start = this.clippedPos(position.row, position.column);
            var end = this.pos(position.row, position.column + text.length);

            this.applyDelta({
                start: start,
                end: end,
                action: "insert",
                lines: [text]
            }, true);

            return this.clonePos(end);
        };

        this.clippedPos = function(row, column) {
            var length = this.getLength();
            if (row === undefined) {
                row = length;
            } else if (row < 0) {
                row = 0;
            } else if (row >= length) {
                row = length - 1;
                column = undefined;
            }
            var line = this.getLine(row);
            if (column == undefined)
                column = line.length;
            column = Math.min(Math.max(column, 0), line.length);
            return {
                row: row,
                column: column
            };
        };

        this.clonePos = function(pos) {
            return {
                row: pos.row,
                column: pos.column
            };
        };

        this.pos = function(row, column) {
            return {
                row: row,
                column: column
            };
        };

        this.$clipPosition = function(position) {
            var length = this.getLength();
            if (position.row >= length) {
                position.row = Math.max(0, length - 1);
                position.column = this.getLine(length - 1).length;
            } else {
                position.row = Math.max(0, position.row);
                position.column = Math.min(Math.max(position.column, 0), this.getLine(position.row).length);
            }
            return position;
        };
        this.insertFullLines = function(row, lines) {
            row = Math.min(Math.max(row, 0), this.getLength());
            var column = 0;
            if (row < this.getLength()) {
                lines = lines.concat([""]);
                column = 0;
            } else {
                lines = [""].concat(lines);
                row--;
                column = this.$lines[row].length;
            }
            this.insertMergedLines({
                row: row,
                column: column
            }, lines);
        };
        this.insertMergedLines = function(position, lines) {
            var start = this.clippedPos(position.row, position.column);
            var end = {
                row: start.row + lines.length - 1,
                column: (lines.length == 1 ? start.column : 0) + lines[lines.length - 1].length
            };

            this.applyDelta({
                start: start,
                end: end,
                action: "insert",
                lines: lines
            });

            return this.clonePos(end);
        };
        this.remove = function(range) {
            var start = this.clippedPos(range.start.row, range.start.column);
            var end = this.clippedPos(range.end.row, range.end.column);
            this.applyDelta({
                start: start,
                end: end,
                action: "remove",
                lines: this.getLinesForRange({
                    start: start,
                    end: end
                })
            });
            return this.clonePos(start);
        };
        this.removeInLine = function(row, startColumn, endColumn) {
            var start = this.clippedPos(row, startColumn);
            var end = this.clippedPos(row, endColumn);

            this.applyDelta({
                start: start,
                end: end,
                action: "remove",
                lines: this.getLinesForRange({
                    start: start,
                    end: end
                })
            }, true);

            return this.clonePos(start);
        };
        this.removeFullLines = function(firstRow, lastRow) {
            firstRow = Math.min(Math.max(0, firstRow), this.getLength() - 1);
            lastRow = Math.min(Math.max(0, lastRow), this.getLength() - 1);
            var deleteFirstNewLine = lastRow == this.getLength() - 1 && firstRow > 0;
            var deleteLastNewLine = lastRow < this.getLength() - 1;
            var startRow = (deleteFirstNewLine ? firstRow - 1 : firstRow);
            var startCol = (deleteFirstNewLine ? this.getLine(startRow).length : 0);
            var endRow = (deleteLastNewLine ? lastRow + 1 : lastRow);
            var endCol = (deleteLastNewLine ? 0 : this.getLine(endRow).length);
            var range = new Range(startRow, startCol, endRow, endCol);
            var deletedLines = this.$lines.slice(firstRow, lastRow + 1);

            this.applyDelta({
                start: range.start,
                end: range.end,
                action: "remove",
                lines: this.getLinesForRange(range)
            });
            return deletedLines;
        };
        this.removeNewLine = function(row) {
            if (row < this.getLength() - 1 && row >= 0) {
                this.applyDelta({
                    start: this.pos(row, this.getLine(row).length),
                    end: this.pos(row + 1, 0),
                    action: "remove",
                    lines: ["", ""]
                });
            }
        };
        this.replace = function(range, text) {
            if (!(range instanceof Range))
                range = Range.fromPoints(range.start, range.end);
            if (text.length === 0 && range.isEmpty())
                return range.start;
            if (text == this.getTextRange(range))
                return range.end;

            this.remove(range);
            var end;
            if (text) {
                end = this.insert(range.start, text);
            } else {
                end = range.start;
            }

            return end;
        };
        this.applyDeltas = function(deltas) {
            for (var i = 0; i < deltas.length; i++) {
                this.applyDelta(deltas[i]);
            }
        };
        this.revertDeltas = function(deltas) {
            for (var i = deltas.length - 1; i >= 0; i--) {
                this.revertDelta(deltas[i]);
            }
        };
        this.applyDelta = function(delta, doNotValidate) {
            var isInsert = delta.action == "insert";
            if (isInsert ? delta.lines.length <= 1 && !delta.lines[0] : !Range.comparePoints(delta.start, delta.end)) {
                return;
            }

            if (isInsert && delta.lines.length > 20000)
                this.$splitAndapplyLargeDelta(delta, 20000);
            applyDelta(this.$lines, delta, doNotValidate);
            this._signal("change", delta);
        };

        this.$splitAndapplyLargeDelta = function(delta, MAX) {
            var lines = delta.lines;
            var l = lines.length;
            var row = delta.start.row;
            var column = delta.start.column;
            var from = 0,
                to = 0;
            do {
                from = to;
                to += MAX - 1;
                var chunk = lines.slice(from, to);
                if (to > l) {
                    delta.lines = chunk;
                    delta.start.row = row + from;
                    delta.start.column = column;
                    break;
                }
                chunk.push("");
                this.applyDelta({
                    start: this.pos(row + from, column),
                    end: this.pos(row + to, column = 0),
                    action: delta.action,
                    lines: chunk
                }, true);
            } while (true);
        };
        this.revertDelta = function(delta) {
            this.applyDelta({
                start: this.clonePos(delta.start),
                end: this.clonePos(delta.end),
                action: (delta.action == "insert" ? "remove" : "insert"),
                lines: delta.lines.slice()
            });
        };
        this.indexToPosition = function(index, startRow) {
            var lines = this.$lines || this.getAllLines();
            var newlineLength = this.getNewLineCharacter().length;
            for (var i = startRow || 0, l = lines.length; i < l; i++) {
                index -= lines[i].length + newlineLength;
                if (index < 0)
                    return {
                        row: i,
                        column: index + lines[i].length + newlineLength
                    };
            }
            return {
                row: l - 1,
                column: lines[l - 1].length
            };
        };
        this.positionToIndex = function(pos, startRow) {
            var lines = this.$lines || this.getAllLines();
            var newlineLength = this.getNewLineCharacter().length;
            var index = 0;
            var row = Math.min(pos.row, lines.length);
            for (var i = startRow || 0; i < row; ++i)
                index += lines[i].length + newlineLength;

            return index + pos.column;
        };

    }).call(Document.prototype);

    exports.Document = Document;
});

define("ace/lib/lang", ["require", "exports", "module"], function(require, exports, module) {
    "use strict";

    exports.last = function(a) {
        return a[a.length - 1];
    };

    exports.stringReverse = function(string) {
        return string.split("").reverse().join("");
    };

    exports.stringRepeat = function(string, count) {
        var result = '';
        while (count > 0) {
            if (count & 1)
                result += string;

            if (count >>= 1)
                string += string;
        }
        return result;
    };

    var trimBeginRegexp = /^\s\s*/;
    var trimEndRegexp = /\s\s*$/;

    exports.stringTrimLeft = function(string) {
        return string.replace(trimBeginRegexp, '');
    };

    exports.stringTrimRight = function(string) {
        return string.replace(trimEndRegexp, '');
    };

    exports.copyObject = function(obj) {
        var copy = {};
        for (var key in obj) {
            copy[key] = obj[key];
        }
        return copy;
    };

    exports.copyArray = function(array) {
        var copy = [];
        for (var i = 0, l = array.length; i < l; i++) {
            if (array[i] && typeof array[i] == "object")
                copy[i] = this.copyObject(array[i]);
            else
                copy[i] = array[i];
        }
        return copy;
    };

    exports.deepCopy = function deepCopy(obj) {
        if (typeof obj !== "object" || !obj)
            return obj;
        var copy;
        if (Array.isArray(obj)) {
            copy = [];
            for (var key = 0; key < obj.length; key++) {
                copy[key] = deepCopy(obj[key]);
            }
            return copy;
        }
        if (Object.prototype.toString.call(obj) !== "[object Object]")
            return obj;

        copy = {};
        for (var key in obj)
            copy[key] = deepCopy(obj[key]);
        return copy;
    };

    exports.arrayToMap = function(arr) {
        var map = {};
        for (var i = 0; i < arr.length; i++) {
            map[arr[i]] = 1;
        }
        return map;

    };

    exports.createMap = function(props) {
        var map = Object.create(null);
        for (var i in props) {
            map[i] = props[i];
        }
        return map;
    };
    exports.arrayRemove = function(array, value) {
        for (var i = 0; i <= array.length; i++) {
            if (value === array[i]) {
                array.splice(i, 1);
            }
        }
    };

    exports.escapeRegExp = function(str) {
        return str.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1');
    };

    exports.escapeHTML = function(str) {
        return str.replace(/&/g, "&#38;").replace(/"/g, "&#34;").replace(/'/g, "&#39;").replace(/</g, "&#60;");
    };

    exports.getMatchOffsets = function(string, regExp) {
        var matches = [];

        string.replace(regExp, function(str) {
            matches.push({
                offset: arguments[arguments.length - 2],
                length: str.length
            });
        });

        return matches;
    };
    exports.deferredCall = function(fcn) {
        var timer = null;
        var callback = function() {
            timer = null;
            fcn();
        };

        var deferred = function(timeout) {
            deferred.cancel();
            timer = setTimeout(callback, timeout || 0);
            return deferred;
        };

        deferred.schedule = deferred;

        deferred.call = function() {
            this.cancel();
            fcn();
            return deferred;
        };

        deferred.cancel = function() {
            clearTimeout(timer);
            timer = null;
            return deferred;
        };

        deferred.isPending = function() {
            return timer;
        };

        return deferred;
    };


    exports.delayedCall = function(fcn, defaultTimeout) {
        var timer = null;
        var callback = function() {
            timer = null;
            fcn();
        };

        var _self = function(timeout) {
            if (timer == null)
                timer = setTimeout(callback, timeout || defaultTimeout);
        };

        _self.delay = function(timeout) {
            timer && clearTimeout(timer);
            timer = setTimeout(callback, timeout || defaultTimeout);
        };
        _self.schedule = _self;

        _self.call = function() {
            this.cancel();
            fcn();
        };

        _self.cancel = function() {
            timer && clearTimeout(timer);
            timer = null;
        };

        _self.isPending = function() {
            return timer;
        };

        return _self;
    };
});

define("ace/worker/mirror", ["require", "exports", "module", "ace/range", "ace/document", "ace/lib/lang"], function(require, exports, module) {
    "use strict";

    var Range = require("../range").Range;
    var Document = require("../document").Document;
    var lang = require("../lib/lang");

    var Mirror = exports.Mirror = function(sender) {
        this.sender = sender;
        var doc = this.doc = new Document("");

        var deferredUpdate = this.deferredUpdate = lang.delayedCall(this.onUpdate.bind(this));

        var _self = this;
        sender.on("change", function(e) {
            var data = e.data;
            if (data[0].start) {
                doc.applyDeltas(data);
            } else {
                for (var i = 0; i < data.length; i += 2) {
                    if (Array.isArray(data[i + 1])) {
                        var d = {
                            action: "insert",
                            start: data[i],
                            lines: data[i + 1]
                        };
                    } else {
                        var d = {
                            action: "remove",
                            start: data[i],
                            end: data[i + 1]
                        };
                    }
                    doc.applyDelta(d, true);
                }
            }
            if (_self.$timeout)
                return deferredUpdate.schedule(_self.$timeout);
            _self.onUpdate();
        });
    };

    (function() {

        this.$timeout = 500;

        this.setTimeout = function(timeout) {
            this.$timeout = timeout;
        };

        this.setValue = function(value) {
            this.doc.setValue(value);
            this.deferredUpdate.schedule(this.$timeout);
        };

        this.getValue = function(callbackId) {
            this.sender.callback(this.doc.getValue(), callbackId);
        };

        this.onUpdate = function() {};

        this.isPending = function() {
            return this.deferredUpdate.isPending();
        };

    }).call(Mirror.prototype);

});

define("ace/mode/javascript/jshint", ["require", "exports", "module"], function(require, exports, module) {
    module.exports = (function outer(modules, cache, entry) {
            var previousRequire = typeof require == "function" && require;

            function newRequire(name, jumped) {
                if (!cache[name]) {
                    if (!modules[name]) {
                        var currentRequire = typeof require == "function" && require;
                        if (!jumped && currentRequire) return currentRequire(name, true);
                        if (previousRequire) return previousRequire(name, true);
                        var err = new Error('Cannot find module \'' + name + '\'');
                        err.code = 'MODULE_NOT_FOUND';
                        throw err;
                    }
                    var m = cache[name] = {
                        exports: {}
                    };
                    modules[name][0].call(m.exports, function(x) {
                        var id = modules[name][1][x];
                        return newRequire(id ? id : x);
                    }, m, m.exports, outer, modules, cache, entry);
                }
                return cache[name].exports;
            }
            for (var i = 0; i < entry.length; i++) newRequire(entry[i]);
            return newRequire(entry[0]);
        })
        ({
            "/node_modules/browserify/node_modules/events/events.js": [function(_dereq_, module, exports) {

                function EventEmitter() {
                    this._events = this._events || {};
                    this._maxListeners = this._maxListeners || undefined;
                }
                module.exports = EventEmitter;
                EventEmitter.EventEmitter = EventEmitter;

                EventEmitter.prototype._events = undefined;
                EventEmitter.prototype._maxListeners = undefined;
                EventEmitter.defaultMaxListeners = 10;
                EventEmitter.prototype.setMaxListeners = function(n) {
                    if (!isNumber(n) || n < 0 || isNaN(n))
                        throw TypeError('n must be a positive number');
                    this._maxListeners = n;
                    return this;
                };

                EventEmitter.prototype.emit = function(type) {
                    var er, handler, len, args, i, listeners;

                    if (!this._events)
                        this._events = {};
                    if (type === 'error') {
                        if (!this._events.error ||
                            (isObject(this._events.error) && !this._events.error.length)) {
                            er = arguments[1];
                            if (er instanceof Error) {
                                throw er; // Unhandled 'error' event
                            }
                            throw TypeError('Uncaught, unspecified "error" event.');
                        }
                    }

                    handler = this._events[type];

                    if (isUndefined(handler))
                        return false;

                    if (isFunction(handler)) {
                        switch (arguments.length) {
                            case 1:
                                handler.call(this);
                                break;
                            case 2:
                                handler.call(this, arguments[1]);
                                break;
                            case 3:
                                handler.call(this, arguments[1], arguments[2]);
                                break;
                            default:
                                len = arguments.length;
                                args = new Array(len - 1);
                                for (i = 1; i < len; i++)
                                    args[i - 1] = arguments[i];
                                handler.apply(this, args);
                        }
                    } else if (isObject(handler)) {
                        len = arguments.length;
                        args = new Array(len - 1);
                        for (i = 1; i < len; i++)
                            args[i - 1] = arguments[i];

                        listeners = handler.slice();
                        len = listeners.length;
                        for (i = 0; i < len; i++)
                            listeners[i].apply(this, args);
                    }

                    return true;
                };

                EventEmitter.prototype.addListener = function(type, listener) {
                    var m;

                    if (!isFunction(listener))
                        throw TypeError('listener must be a function');

                    if (!this._events)
                        this._events = {};
                    if (this._events.newListener)
                        this.emit('newListener', type,
                            isFunction(listener.listener) ?
                            listener.listener : listener);

                    if (!this._events[type])
                        this._events[type] = listener;
                    else if (isObject(this._events[type]))
                        this._events[type].push(listener);
                    else
                        this._events[type] = [this._events[type], listener];
                    if (isObject(this._events[type]) && !this._events[type].warned) {
                        var m;
                        if (!isUndefined(this._maxListeners)) {
                            m = this._maxListeners;
                        } else {
                            m = EventEmitter.defaultMaxListeners;
                        }

                        if (m && m > 0 && this._events[type].length > m) {
                            this._events[type].warned = true;
                            console.error('(node) warning: possible EventEmitter memory ' +
                                'leak detected. %d listeners added. ' +
                                'Use emitter.setMaxListeners() to increase limit.',
                                this._events[type].length);
                            if (typeof console.trace === 'function') {
                                console.trace();
                            }
                        }
                    }

                    return this;
                };

                EventEmitter.prototype.on = EventEmitter.prototype.addListener;

                EventEmitter.prototype.once = function(type, listener) {
                    if (!isFunction(listener))
                        throw TypeError('listener must be a function');

                    var fired = false;

                    function g() {
                        this.removeListener(type, g);

                        if (!fired) {
                            fired = true;
                            listener.apply(this, arguments);
                        }
                    }

                    g.listener = listener;
                    this.on(type, g);

                    return this;
                };
                EventEmitter.prototype.removeListener = function(type, listener) {
                    var list, position, length, i;

                    if (!isFunction(listener))
                        throw TypeError('listener must be a function');

                    if (!this._events || !this._events[type])
                        return this;

                    list = this._events[type];
                    length = list.length;
                    position = -1;

                    if (list === listener ||
                        (isFunction(list.listener) && list.listener === listener)) {
                        delete this._events[type];
                        if (this._events.removeListener)
                            this.emit('removeListener', type, listener);

                    } else if (isObject(list)) {
                        for (i = length; i-- > 0;) {
                            if (list[i] === listener ||
                                (list[i].listener && list[i].listener === listener)) {
                                position = i;
                                break;
                            }
                        }

                        if (position < 0)
                            return this;

                        if (list.length === 1) {
                            list.length = 0;
                            delete this._events[type];
                        } else {
                            list.splice(position, 1);
                        }

                        if (this._events.removeListener)
                            this.emit('removeListener', type, listener);
                    }

                    return this;
                };

                EventEmitter.prototype.removeAllListeners = function(type) {
                    var key, listeners;

                    if (!this._events)
                        return this;
                    if (!this._events.removeListener) {
                        if (arguments.length === 0)
                            this._events = {};
                        else if (this._events[type])
                            delete this._events[type];
                        return this;
                    }
                    if (arguments.length === 0) {
                        for (key in this._events) {
                            if (key === 'removeListener') continue;
                            this.removeAllListeners(key);
                        }
                        this.removeAllListeners('removeListener');
                        this._events = {};
                        return this;
                    }

                    listeners = this._events[type];

                    if (isFunction(listeners)) {
                        this.removeListener(type, listeners);
                    } else {
                        while (listeners.length)
                            this.removeListener(type, listeners[listeners.length - 1]);
                    }
                    delete this._events[type];

                    return this;
                };

                EventEmitter.prototype.listeners = function(type) {
                    var ret;
                    if (!this._events || !this._events[type])
                        ret = [];
                    else if (isFunction(this._events[type]))
                        ret = [this._events[type]];
                    else
                        ret = this._events[type].slice();
                    return ret;
                };

                EventEmitter.listenerCount = function(emitter, type) {
                    var ret;
                    if (!emitter._events || !emitter._events[type])
                        ret = 0;
                    else if (isFunction(emitter._events[type]))
                        ret = 1;
                    else
                        ret = emitter._events[type].length;
                    return ret;
                };

                function isFunction(arg) {
                    return typeof arg === 'function';
                }

                function isNumber(arg) {
                    return typeof arg === 'number';
                }

                function isObject(arg) {
                    return typeof arg === 'object' && arg !== null;
                }

                function isUndefined(arg) {
                    return arg === void 0;
                }

            }, {}],
            "/node_modules/jshint/data/ascii-identifier-data.js": [function(_dereq_, module, exports) {
                var identifierStartTable = [];

                for (var i = 0; i < 128; i++) {
                    identifierStartTable[i] =
                        i === 36 || // $
                        i >= 65 && i <= 90 || // A-Z
                        i === 95 || // _
                        i >= 97 && i <= 122; // a-z
                }

                var identifierPartTable = [];

                for (var i = 0; i < 128; i++) {
                    identifierPartTable[i] =
                        identifierStartTable[i] || // $, _, A-Z, a-z
                        i >= 48 && i <= 57; // 0-9
                }

                module.exports = {
                    asciiIdentifierStartTable: identifierStartTable,
                    asciiIdentifierPartTable: identifierPartTable
                };

            }, {}],
            "/node_modules/jshint/lodash.js": [function(_dereq_, module, exports) {
                (function(global) {;
                    (function() {

                        var undefined;

                        var VERSION = '3.7.0';

                        var FUNC_ERROR_TEXT = 'Expected a function';

                        var argsTag = '[object Arguments]',
                            arrayTag = '[object Array]',
                            boolTag = '[object Boolean]',
                            dateTag = '[object Date]',
                            errorTag = '[object Error]',
                            funcTag = '[object Function]',
                            mapTag = '[object Map]',
                            numberTag = '[object Number]',
                            objectTag = '[object Object]',
                            regexpTag = '[object RegExp]',
                            setTag = '[object Set]',
                            stringTag = '[object String]',
                            weakMapTag = '[object WeakMap]';

                        var arrayBufferTag = '[object ArrayBuffer]',
                            float32Tag = '[object Float32Array]',
                            float64Tag = '[object Float64Array]',
                            int8Tag = '[object Int8Array]',
                            int16Tag = '[object Int16Array]',
                            int32Tag = '[object Int32Array]',
                            uint8Tag = '[object Uint8Array]',
                            uint8ClampedTag = '[object Uint8ClampedArray]',
                            uint16Tag = '[object Uint16Array]',
                            uint32Tag = '[object Uint32Array]';

                        var reIsDeepProp = /\.|\[(?:[^[\]]+|(["'])(?:(?!\1)[^\n\\]|\\.)*?)\1\]/,
                            reIsPlainProp = /^\w*$/,
                            rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g;

                        var reRegExpChars = /[.*+?^${}()|[\]\/\\]/g,
                            reHasRegExpChars = RegExp(reRegExpChars.source);

                        var reEscapeChar = /\\(\\)?/g;

                        var reFlags = /\w*$/;

                        var reIsHostCtor = /^\[object .+?Constructor\]$/;

                        var typedArrayTags = {};
                        typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
                            typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
                            typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
                            typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
                            typedArrayTags[uint32Tag] = true;
                        typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
                            typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
                            typedArrayTags[dateTag] = typedArrayTags[errorTag] =
                            typedArrayTags[funcTag] = typedArrayTags[mapTag] =
                            typedArrayTags[numberTag] = typedArrayTags[objectTag] =
                            typedArrayTags[regexpTag] = typedArrayTags[setTag] =
                            typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false;

                        var cloneableTags = {};
                        cloneableTags[argsTag] = cloneableTags[arrayTag] =
                            cloneableTags[arrayBufferTag] = cloneableTags[boolTag] =
                            cloneableTags[dateTag] = cloneableTags[float32Tag] =
                            cloneableTags[float64Tag] = cloneableTags[int8Tag] =
                            cloneableTags[int16Tag] = cloneableTags[int32Tag] =
                            cloneableTags[numberTag] = cloneableTags[objectTag] =
                            cloneableTags[regexpTag] = cloneableTags[stringTag] =
                            cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =
                            cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
                        cloneableTags[errorTag] = cloneableTags[funcTag] =
                            cloneableTags[mapTag] = cloneableTags[setTag] =
                            cloneableTags[weakMapTag] = false;

                        var objectTypes = {
                            'function': true,
                            'object': true
                        };

                        var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;

                        var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;

                        var freeGlobal = freeExports && freeModule && typeof global == 'object' && global && global.Object && global;

                        var freeSelf = objectTypes[typeof self] && self && self.Object && self;

                        var freeWindow = objectTypes[typeof window] && window && window.Object && window;

                        var moduleExports = freeModule && freeModule.exports === freeExports && freeExports;

                        var root = freeGlobal || ((freeWindow !== (this && this.window)) && freeWindow) || freeSelf || this;

                        function baseFindIndex(array, predicate, fromRight) {
                            var length = array.length,
                                index = fromRight ? length : -1;

                            while ((fromRight ? index-- : ++index < length)) {
                                if (predicate(array[index], index, array)) {
                                    return index;
                                }
                            }
                            return -1;
                        }

                        function baseIndexOf(array, value, fromIndex) {
                            if (value !== value) {
                                return indexOfNaN(array, fromIndex);
                            }
                            var index = fromIndex - 1,
                                length = array.length;

                            while (++index < length) {
                                if (array[index] === value) {
                                    return index;
                                }
                            }
                            return -1;
                        }

                        function baseIsFunction(value) {
                            return typeof value == 'function' || false;
                        }

                        function baseToString(value) {
                            if (typeof value == 'string') {
                                return value;
                            }
                            return value == null ? '' : (value + '');
                        }

                        function indexOfNaN(array, fromIndex, fromRight) {
                            var length = array.length,
                                index = fromIndex + (fromRight ? 0 : -1);

                            while ((fromRight ? index-- : ++index < length)) {
                                var other = array[index];
                                if (other !== other) {
                                    return index;
                                }
                            }
                            return -1;
                        }

                        function isObjectLike(value) {
                            return !!value && typeof value == 'object';
                        }

                        var arrayProto = Array.prototype,
                            objectProto = Object.prototype;

                        var fnToString = Function.prototype.toString;

                        var hasOwnProperty = objectProto.hasOwnProperty;

                        var objToString = objectProto.toString;

                        var reIsNative = RegExp('^' +
                            escapeRegExp(objToString)
                            .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
                        );

                        var ArrayBuffer = isNative(ArrayBuffer = root.ArrayBuffer) && ArrayBuffer,
                            bufferSlice = isNative(bufferSlice = ArrayBuffer && new ArrayBuffer(0).slice) && bufferSlice,
                            floor = Math.floor,
                            getOwnPropertySymbols = isNative(getOwnPropertySymbols = Object.getOwnPropertySymbols) && getOwnPropertySymbols,
                            getPrototypeOf = isNative(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf,
                            push = arrayProto.push,
                            preventExtensions = isNative(Object.preventExtensions = Object.preventExtensions) && preventExtensions,
                            propertyIsEnumerable = objectProto.propertyIsEnumerable,
                            Uint8Array = isNative(Uint8Array = root.Uint8Array) && Uint8Array;

                        var Float64Array = (function() {
                            try {
                                var func = isNative(func = root.Float64Array) && func,
                                    result = new func(new ArrayBuffer(10), 0, 1) && func;
                            } catch (e) {}
                            return result;
                        }());

                        var nativeAssign = (function() {
                            var object = {
                                    '1': 0
                                },
                                func = preventExtensions && isNative(func = Object.assign) && func;

                            try {
                                func(preventExtensions(object), 'xo');
                            } catch (e) {}
                            return !object[1] && func;
                        }());

                        var nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray,
                            nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys,
                            nativeMax = Math.max,
                            nativeMin = Math.min;

                        var NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY;

                        var MAX_ARRAY_LENGTH = Math.pow(2, 32) - 1,
                            MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1,
                            HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;

                        var FLOAT64_BYTES_PER_ELEMENT = Float64Array ? Float64Array.BYTES_PER_ELEMENT : 0;

                        var MAX_SAFE_INTEGER = Math.pow(2, 53) - 1;

                        function lodash() {}

                        var support = lodash.support = {};

                        (function(x) {
                            var Ctor = function() {
                                    this.x = x;
                                },
                                object = {
                                    '0': x,
                                    'length': x
                                },
                                props = [];

                            Ctor.prototype = {
                                'valueOf': x,
                                'y': x
                            };
                            for (var key in new Ctor) {
                                props.push(key);
                            }

                            support.funcDecomp = /\bthis\b/.test(function() {
                                return this;
                            });

                            support.funcNames = typeof Function.name == 'string';

                            try {
                                support.nonEnumArgs = !propertyIsEnumerable.call(arguments, 1);
                            } catch (e) {
                                support.nonEnumArgs = true;
                            }
                        }(1, 0));

                        function arrayCopy(source, array) {
                            var index = -1,
                                length = source.length;

                            array || (array = Array(length));
                            while (++index < length) {
                                array[index] = source[index];
                            }
                            return array;
                        }

                        function arrayEach(array, iteratee) {
                            var index = -1,
                                length = array.length;

                            while (++index < length) {
                                if (iteratee(array[index], index, array) === false) {
                                    break;
                                }
                            }
                            return array;
                        }

                        function arrayFilter(array, predicate) {
                            var index = -1,
                                length = array.length,
                                resIndex = -1,
                                result = [];

                            while (++index < length) {
                                var value = array[index];
                                if (predicate(value, index, array)) {
                                    result[++resIndex] = value;
                                }
                            }
                            return result;
                        }

                        function arrayMap(array, iteratee) {
                            var index = -1,
                                length = array.length,
                                result = Array(length);

                            while (++index < length) {
                                result[index] = iteratee(array[index], index, array);
                            }
                            return result;
                        }

                        function arrayMax(array) {
                            var index = -1,
                                length = array.length,
                                result = NEGATIVE_INFINITY;

                            while (++index < length) {
                                var value = array[index];
                                if (value > result) {
                                    result = value;
                                }
                            }
                            return result;
                        }

                        function arraySome(array, predicate) {
                            var index = -1,
                                length = array.length;

                            while (++index < length) {
                                if (predicate(array[index], index, array)) {
                                    return true;
                                }
                            }
                            return false;
                        }

                        function assignWith(object, source, customizer) {
                            var props = keys(source);
                            push.apply(props, getSymbols(source));

                            var index = -1,
                                length = props.length;

                            while (++index < length) {
                                var key = props[index],
                                    value = object[key],
                                    result = customizer(value, source[key], key, object, source);

                                if ((result === result ? (result !== value) : (value === value)) ||
                                    (value === undefined && !(key in object))) {
                                    object[key] = result;
                                }
                            }
                            return object;
                        }

                        var baseAssign = nativeAssign || function(object, source) {
                            return source == null ? object : baseCopy(source, getSymbols(source), baseCopy(source, keys(source), object));
                        };

                        function baseCopy(source, props, object) {
                            object || (object = {});

                            var index = -1,
                                length = props.length;

                            while (++index < length) {
                                var key = props[index];
                                object[key] = source[key];
                            }
                            return object;
                        }

                        function baseCallback(func, thisArg, argCount) {
                            var type = typeof func;
                            if (type == 'function') {
                                return thisArg === undefined ? func : bindCallback(func, thisArg, argCount);
                            }
                            if (func == null) {
                                return identity;
                            }
                            if (type == 'object') {
                                return baseMatches(func);
                            }
                            return thisArg === undefined ? property(func) : baseMatchesProperty(func, thisArg);
                        }

                        function baseClone(value, isDeep, customizer, key, object, stackA, stackB) {
                            var result;
                            if (customizer) {
                                result = object ? customizer(value, key, object) : customizer(value);
                            }
                            if (result !== undefined) {
                                return result;
                            }
                            if (!isObject(value)) {
                                return value;
                            }
                            var isArr = isArray(value);
                            if (isArr) {
                                result = initCloneArray(value);
                                if (!isDeep) {
                                    return arrayCopy(value, result);
                                }
                            } else {
                                var tag = objToString.call(value),
                                    isFunc = tag == funcTag;

                                if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
                                    result = initCloneObject(isFunc ? {} : value);
                                    if (!isDeep) {
                                        return baseAssign(result, value);
                                    }
                                } else {
                                    return cloneableTags[tag] ? initCloneByTag(value, tag, isDeep) : (object ? value : {});
                                }
                            }
                            stackA || (stackA = []);
                            stackB || (stackB = []);

                            var length = stackA.length;
                            while (length--) {
                                if (stackA[length] == value) {
                                    return stackB[length];
                                }
                            }
                            stackA.push(value);
                            stackB.push(result);

                            (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) {
                                result[key] = baseClone(subValue, isDeep, customizer, key, value, stackA, stackB);
                            });
                            return result;
                        }

                        var baseEach = createBaseEach(baseForOwn);

                        function baseFilter(collection, predicate) {
                            var result = [];
                            baseEach(collection, function(value, index, collection) {
                                if (predicate(value, index, collection)) {
                                    result.push(value);
                                }
                            });
                            return result;
                        }

                        var baseFor = createBaseFor();

                        function baseForIn(object, iteratee) {
                            return baseFor(object, iteratee, keysIn);
                        }

                        function baseForOwn(object, iteratee) {
                            return baseFor(object, iteratee, keys);
                        }

                        function baseGet(object, path, pathKey) {
                            if (object == null) {
                                return;
                            }
                            if (pathKey !== undefined && pathKey in toObject(object)) {
                                path = [pathKey];
                            }
                            var index = -1,
                                length = path.length;

                            while (object != null && ++index < length) {
                                var result = object = object[path[index]];
                            }
                            return result;
                        }

                        function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) {
                            if (value === other) {
                                return value !== 0 || (1 / value == 1 / other);
                            }
                            var valType = typeof value,
                                othType = typeof other;

                            if ((valType != 'function' && valType != 'object' && othType != 'function' && othType != 'object') ||
                                value == null || other == null) {
                                return value !== value && other !== other;
                            }
                            return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB);
                        }

                        function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) {
                            var objIsArr = isArray(object),
                                othIsArr = isArray(other),
                                objTag = arrayTag,
                                othTag = arrayTag;

                            if (!objIsArr) {
                                objTag = objToString.call(object);
                                if (objTag == argsTag) {
                                    objTag = objectTag;
                                } else if (objTag != objectTag) {
                                    objIsArr = isTypedArray(object);
                                }
                            }
                            if (!othIsArr) {
                                othTag = objToString.call(other);
                                if (othTag == argsTag) {
                                    othTag = objectTag;
                                } else if (othTag != objectTag) {
                                    othIsArr = isTypedArray(other);
                                }
                            }
                            var objIsObj = objTag == objectTag,
                                othIsObj = othTag == objectTag,
                                isSameTag = objTag == othTag;

                            if (isSameTag && !(objIsArr || objIsObj)) {
                                return equalByTag(object, other, objTag);
                            }
                            if (!isLoose) {
                                var valWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
                                    othWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');

                                if (valWrapped || othWrapped) {
                                    return equalFunc(valWrapped ? object.value() : object, othWrapped ? other.value() : other, customizer, isLoose, stackA, stackB);
                                }
                            }
                            if (!isSameTag) {
                                return false;
                            }
                            stackA || (stackA = []);
                            stackB || (stackB = []);

                            var length = stackA.length;
                            while (length--) {
                                if (stackA[length] == object) {
                                    return stackB[length] == other;
                                }
                            }
                            stackA.push(object);
                            stackB.push(other);

                            var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB);

                            stackA.pop();
                            stackB.pop();

                            return result;
                        }

                        function baseIsMatch(object, props, values, strictCompareFlags, customizer) {
                            var index = -1,
                                length = props.length,
                                noCustomizer = !customizer;

                            while (++index < length) {
                                if ((noCustomizer && strictCompareFlags[index]) ? values[index] !== object[props[index]] : !(props[index] in object)) {
                                    return false;
                                }
                            }
                            index = -1;
                            while (++index < length) {
                                var key = props[index],
                                    objValue = object[key],
                                    srcValue = values[index];

                                if (noCustomizer && strictCompareFlags[index]) {
                                    var result = objValue !== undefined || (key in object);
                                } else {
                                    result = customizer ? customizer(objValue, srcValue, key) : undefined;
                                    if (result === undefined) {
                                        result = baseIsEqual(srcValue, objValue, customizer, true);
                                    }
                                }
                                if (!result) {
                                    return false;
                                }
                            }
                            return true;
                        }

                        function baseMatches(source) {
                            var props = keys(source),
                                length = props.length;

                            if (!length) {
                                return constant(true);
                            }
                            if (length == 1) {
                                var key = props[0],
                                    value = source[key];

                                if (isStrictComparable(value)) {
                                    return function(object) {
                                        if (object == null) {
                                            return false;
                                        }
                                        return object[key] === value && (value !== undefined || (key in toObject(object)));
                                    };
                                }
                            }
                            var values = Array(length),
                                strictCompareFlags = Array(length);

                            while (length--) {
                                value = source[props[length]];
                                values[length] = value;
                                strictCompareFlags[length] = isStrictComparable(value);
                            }
                            return function(object) {
                                return object != null && baseIsMatch(toObject(object), props, values, strictCompareFlags);
                            };
                        }

                        function baseMatchesProperty(path, value) {
                            var isArr = isArray(path),
                                isCommon = isKey(path) && isStrictComparable(value),
                                pathKey = (path + '');

                            path = toPath(path);
                            return function(object) {
                                if (object == null) {
                                    return false;
                                }
                                var key = pathKey;
                                object = toObject(object);
                                if ((isArr || !isCommon) && !(key in object)) {
                                    object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));
                                    if (object == null) {
                                        return false;
                                    }
                                    key = last(path);
                                    object = toObject(object);
                                }
                                return object[key] === value ? (value !== undefined || (key in object)) : baseIsEqual(value, object[key], null, true);
                            };
                        }

                        function baseMerge(object, source, customizer, stackA, stackB) {
                            if (!isObject(object)) {
                                return object;
                            }
                            var isSrcArr = isLength(source.length) && (isArray(source) || isTypedArray(source));
                            if (!isSrcArr) {
                                var props = keys(source);
                                push.apply(props, getSymbols(source));
                            }
                            arrayEach(props || source, function(srcValue, key) {
                                if (props) {
                                    key = srcValue;
                                    srcValue = source[key];
                                }
                                if (isObjectLike(srcValue)) {
                                    stackA || (stackA = []);
                                    stackB || (stackB = []);
                                    baseMergeDeep(object, source, key, baseMerge, customizer, stackA, stackB);
                                } else {
                                    var value = object[key],
                                        result = customizer ? customizer(value, srcValue, key, object, source) : undefined,
                                        isCommon = result === undefined;

                                    if (isCommon) {
                                        result = srcValue;
                                    }
                                    if ((isSrcArr || result !== undefined) &&
                                        (isCommon || (result === result ? (result !== value) : (value === value)))) {
                                        object[key] = result;
                                    }
                                }
                            });
                            return object;
                        }

                        function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stackB) {
                            var length = stackA.length,
                                srcValue = source[key];

                            while (length--) {
                                if (stackA[length] == srcValue) {
                                    object[key] = stackB[length];
                                    return;
                                }
                            }
                            var value = object[key],
                                result = customizer ? customizer(value, srcValue, key, object, source) : undefined,
                                isCommon = result === undefined;

                            if (isCommon) {
                                result = srcValue;
                                if (isLength(srcValue.length) && (isArray(srcValue) || isTypedArray(srcValue))) {
                                    result = isArray(value) ? value : (getLength(value) ? arrayCopy(value) : []);
                                } else if (isPlainObject(srcValue) || isArguments(srcValue)) {
                                    result = isArguments(value) ? toPlainObject(value) : (isPlainObject(value) ? value : {});
                                } else {
                                    isCommon = false;
                                }
                            }
                            stackA.push(srcValue);
                            stackB.push(result);

                            if (isCommon) {
                                object[key] = mergeFunc(result, srcValue, customizer, stackA, stackB);
                            } else if (result === result ? (result !== value) : (value === value)) {
                                object[key] = result;
                            }
                        }

                        function baseProperty(key) {
                            return function(object) {
                                return object == null ? undefined : object[key];
                            };
                        }

                        function basePropertyDeep(path) {
                            var pathKey = (path + '');
                            path = toPath(path);
                            return function(object) {
                                return baseGet(object, path, pathKey);
                            };
                        }

                        function baseSlice(array, start, end) {
                            var index = -1,
                                length = array.length;

                            start = start == null ? 0 : (+start || 0);
                            if (start < 0) {
                                start = -start > length ? 0 : (length + start);
                            }
                            end = (end === undefined || end > length) ? length : (+end || 0);
                            if (end < 0) {
                                end += length;
                            }
                            length = start > end ? 0 : ((end - start) >>> 0);
                            start >>>= 0;

                            var result = Array(length);
                            while (++index < length) {
                                result[index] = array[index + start];
                            }
                            return result;
                        }

                        function baseSome(collection, predicate) {
                            var result;

                            baseEach(collection, function(value, index, collection) {
                                result = predicate(value, index, collection);
                                return !result;
                            });
                            return !!result;
                        }

                        function baseValues(object, props) {
                            var index = -1,
                                length = props.length,
                                result = Array(length);

                            while (++index < length) {
                                result[index] = object[props[index]];
                            }
                            return result;
                        }

                        function binaryIndex(array, value, retHighest) {
                            var low = 0,
                                high = array ? array.length : low;

                            if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {
                                while (low < high) {
                                    var mid = (low + high) >>> 1,
                                        computed = array[mid];

                                    if (retHighest ? (computed <= value) : (computed < value)) {
                                        low = mid + 1;
                                    } else {
                                        high = mid;
                                    }
                                }
                                return high;
                            }
                            return binaryIndexBy(array, value, identity, retHighest);
                        }

                        function binaryIndexBy(array, value, iteratee, retHighest) {
                            value = iteratee(value);

                            var low = 0,
                                high = array ? array.length : 0,
                                valIsNaN = value !== value,
                                valIsUndef = value === undefined;

                            while (low < high) {
                                var mid = floor((low + high) / 2),
                                    computed = iteratee(array[mid]),
                                    isReflexive = computed === computed;

                                if (valIsNaN) {
                                    var setLow = isReflexive || retHighest;
                                } else if (valIsUndef) {
                                    setLow = isReflexive && (retHighest || computed !== undefined);
                                } else {
                                    setLow = retHighest ? (computed <= value) : (computed < value);
                                }
                                if (setLow) {
                                    low = mid + 1;
                                } else {
                                    high = mid;
                                }
                            }
                            return nativeMin(high, MAX_ARRAY_INDEX);
                        }

                        function bindCallback(func, thisArg, argCount) {
                            if (typeof func != 'function') {
                                return identity;
                            }
                            if (thisArg === undefined) {
                                return func;
                            }
                            switch (argCount) {
                                case 1:
                                    return function(value) {
                                        return func.call(thisArg, value);
                                    };
                                case 3:
                                    return function(value, index, collection) {
                                        return func.call(thisArg, value, index, collection);
                                    };
                                case 4:
                                    return function(accumulator, value, index, collection) {
                                        return func.call(thisArg, accumulator, value, index, collection);
                                    };
                                case 5:
                                    return function(value, other, key, object, source) {
                                        return func.call(thisArg, value, other, key, object, source);
                                    };
                            }
                            return function() {
                                return func.apply(thisArg, arguments);
                            };
                        }

                        function bufferClone(buffer) {
                            return bufferSlice.call(buffer, 0);
                        }
                        if (!bufferSlice) {
                            bufferClone = !(ArrayBuffer && Uint8Array) ? constant(null) : function(buffer) {
                                var byteLength = buffer.byteLength,
                                    floatLength = Float64Array ? floor(byteLength / FLOAT64_BYTES_PER_ELEMENT) : 0,
                                    offset = floatLength * FLOAT64_BYTES_PER_ELEMENT,
                                    result = new ArrayBuffer(byteLength);

                                if (floatLength) {
                                    var view = new Float64Array(result, 0, floatLength);
                                    view.set(new Float64Array(buffer, 0, floatLength));
                                }
                                if (byteLength != offset) {
                                    view = new Uint8Array(result, offset);
                                    view.set(new Uint8Array(buffer, offset));
                                }
                                return result;
                            };
                        }

                        function createAssigner(assigner) {
                            return restParam(function(object, sources) {
                                var index = -1,
                                    length = object == null ? 0 : sources.length,
                                    customizer = length > 2 && sources[length - 2],
                                    guard = length > 2 && sources[2],
                                    thisArg = length > 1 && sources[length - 1];

                                if (typeof customizer == 'function') {
                                    customizer = bindCallback(customizer, thisArg, 5);
                                    length -= 2;
                                } else {
                                    customizer = typeof thisArg == 'function' ? thisArg : null;
                                    length -= (customizer ? 1 : 0);
                                }
                                if (guard && isIterateeCall(sources[0], sources[1], guard)) {
                                    customizer = length < 3 ? null : customizer;
                                    length = 1;
                                }
                                while (++index < length) {
                                    var source = sources[index];
                                    if (source) {
                                        assigner(object, source, customizer);
                                    }
                                }
                                return object;
                            });
                        }

                        function createBaseEach(eachFunc, fromRight) {
                            return function(collection, iteratee) {
                                var length = collection ? getLength(collection) : 0;
                                if (!isLength(length)) {
                                    return eachFunc(collection, iteratee);
                                }
                                var index = fromRight ? length : -1,
                                    iterable = toObject(collection);

                                while ((fromRight ? index-- : ++index < length)) {
                                    if (iteratee(iterable[index], index, iterable) === false) {
                                        break;
                                    }
                                }
                                return collection;
                            };
                        }

                        function createBaseFor(fromRight) {
                            return function(object, iteratee, keysFunc) {
                                var iterable = toObject(object),
                                    props = keysFunc(object),
                                    length = props.length,
                                    index = fromRight ? length : -1;

                                while ((fromRight ? index-- : ++index < length)) {
                                    var key = props[index];
                                    if (iteratee(iterable[key], key, iterable) === false) {
                                        break;
                                    }
                                }
                                return object;
                            };
                        }

                        function createFindIndex(fromRight) {
                            return function(array, predicate, thisArg) {
                                if (!(array && array.length)) {
                                    return -1;
                                }
                                predicate = getCallback(predicate, thisArg, 3);
                                return baseFindIndex(array, predicate, fromRight);
                            };
                        }

                        function createForEach(arrayFunc, eachFunc) {
                            return function(collection, iteratee, thisArg) {
                                return (typeof iteratee == 'function' && thisArg === undefined && isArray(collection)) ? arrayFunc(collection, iteratee) : eachFunc(collection, bindCallback(iteratee, thisArg, 3));
                            };
                        }

                        function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) {
                            var index = -1,
                                arrLength = array.length,
                                othLength = other.length,
                                result = true;

                            if (arrLength != othLength && !(isLoose && othLength > arrLength)) {
                                return false;
                            }
                            while (result && ++index < arrLength) {
                                var arrValue = array[index],
                                    othValue = other[index];

                                result = undefined;
                                if (customizer) {
                                    result = isLoose ? customizer(othValue, arrValue, index) : customizer(arrValue, othValue, index);
                                }
                                if (result === undefined) {
                                    if (isLoose) {
                                        var othIndex = othLength;
                                        while (othIndex--) {
                                            othValue = other[othIndex];
                                            result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB);
                                            if (result) {
                                                break;
                                            }
                                        }
                                    } else {
                                        result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB);
                                    }
                                }
                            }
                            return !!result;
                        }

                        function equalByTag(object, other, tag) {
                            switch (tag) {
                                case boolTag:
                                case dateTag:
                                    return +object == +other;

                                case errorTag:
                                    return object.name == other.name && object.message == other.message;

                                case numberTag:
                                    return (object != +object) ? other != +other : (object == 0 ? ((1 / object) == (1 / other)) : object == +other);

                                case regexpTag:
                                case stringTag:
                                    return object == (other + '');
                            }
                            return false;
                        }

                        function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) {
                            var objProps = keys(object),
                                objLength = objProps.length,
                                othProps = keys(other),
                                othLength = othProps.length;

                            if (objLength != othLength && !isLoose) {
                                return false;
                            }
                            var skipCtor = isLoose,
                                index = -1;

                            while (++index < objLength) {
                                var key = objProps[index],
                                    result = isLoose ? key in other : hasOwnProperty.call(other, key);

                                if (result) {
                                    var objValue = object[key],
                                        othValue = other[key];

                                    result = undefined;
                                    if (customizer) {
                                        result = isLoose ? customizer(othValue, objValue, key) : customizer(objValue, othValue, key);
                                    }
                                    if (result === undefined) {
                                        result = (objValue && objValue === othValue) || equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB);
                                    }
                                }
                                if (!result) {
                                    return false;
                                }
                                skipCtor || (skipCtor = key == 'constructor');
                            }
                            if (!skipCtor) {
                                var objCtor = object.constructor,
                                    othCtor = other.constructor;

                                if (objCtor != othCtor &&
                                    ('constructor' in object && 'constructor' in other) &&
                                    !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
                                        typeof othCtor == 'function' && othCtor instanceof othCtor)) {
                                    return false;
                                }
                            }
                            return true;
                        }

                        function getCallback(func, thisArg, argCount) {
                            var result = lodash.callback || callback;
                            result = result === callback ? baseCallback : result;
                            return argCount ? result(func, thisArg, argCount) : result;
                        }

                        function getIndexOf(collection, target, fromIndex) {
                            var result = lodash.indexOf || indexOf;
                            result = result === indexOf ? baseIndexOf : result;
                            return collection ? result(collection, target, fromIndex) : result;
                        }

                        var getLength = baseProperty('length');

                        var getSymbols = !getOwnPropertySymbols ? constant([]) : function(object) {
                            return getOwnPropertySymbols(toObject(object));
                        };

                        function initCloneArray(array) {
                            var length = array.length,
                                result = new array.constructor(length);

                            if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
                                result.index = array.index;
                                result.input = array.input;
                            }
                            return result;
                        }

                        function initCloneObject(object) {
                            var Ctor = object.constructor;
                            if (!(typeof Ctor == 'function' && Ctor instanceof Ctor)) {
                                Ctor = Object;
                            }
                            return new Ctor;
                        }

                        function initCloneByTag(object, tag, isDeep) {
                            var Ctor = object.constructor;
                            switch (tag) {
                                case arrayBufferTag:
                                    return bufferClone(object);

                                case boolTag:
                                case dateTag:
                                    return new Ctor(+object);

                                case float32Tag:
                                case float64Tag:
                                case int8Tag:
                                case int16Tag:
                                case int32Tag:
                                case uint8Tag:
                                case uint8ClampedTag:
                                case uint16Tag:
                                case uint32Tag:
                                    var buffer = object.buffer;
                                    return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length);

                                case numberTag:
                                case stringTag:
                                    return new Ctor(object);

                                case regexpTag:
                                    var result = new Ctor(object.source, reFlags.exec(object));
                                    result.lastIndex = object.lastIndex;
                            }
                            return result;
                        }

                        function isIndex(value, length) {
                            value = +value;
                            length = length == null ? MAX_SAFE_INTEGER : length;
                            return value > -1 && value % 1 == 0 && value < length;
                        }

                        function isIterateeCall(value, index, object) {
                            if (!isObject(object)) {
                                return false;
                            }
                            var type = typeof index;
                            if (type == 'number') {
                                var length = getLength(object),
                                    prereq = isLength(length) && isIndex(index, length);
                            } else {
                                prereq = type == 'string' && index in object;
                            }
                            if (prereq) {
                                var other = object[index];
                                return value === value ? (value === other) : (other !== other);
                            }
                            return false;
                        }

                        function isKey(value, object) {
                            var type = typeof value;
                            if ((type == 'string' && reIsPlainProp.test(value)) || type == 'number') {
                                return true;
                            }
                            if (isArray(value)) {
                                return false;
                            }
                            var result = !reIsDeepProp.test(value);
                            return result || (object != null && value in toObject(object));
                        }

                        function isLength(value) {
                            return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
                        }

                        function isStrictComparable(value) {
                            return value === value && (value === 0 ? ((1 / value) > 0) : !isObject(value));
                        }

                        function shimIsPlainObject(value) {
                            var Ctor,
                                support = lodash.support;

                            if (!(isObjectLike(value) && objToString.call(value) == objectTag) ||
                                (!hasOwnProperty.call(value, 'constructor') &&
                                    (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor)))) {
                                return false;
                            }
                            var result;
                            baseForIn(value, function(subValue, key) {
                                result = key;
                            });
                            return result === undefined || hasOwnProperty.call(value, result);
                        }

                        function shimKeys(object) {
                            var props = keysIn(object),
                                propsLength = props.length,
                                length = propsLength && object.length,
                                support = lodash.support;

                            var allowIndexes = length && isLength(length) &&
                                (isArray(object) || (support.nonEnumArgs && isArguments(object)));

                            var index = -1,
                                result = [];

                            while (++index < propsLength) {
                                var key = props[index];
                                if ((allowIndexes && isIndex(key, length)) || hasOwnProperty.call(object, key)) {
                                    result.push(key);
                                }
                            }
                            return result;
                        }

                        function toObject(value) {
                            return isObject(value) ? value : Object(value);
                        }

                        function toPath(value) {
                            if (isArray(value)) {
                                return value;
                            }
                            var result = [];
                            baseToString(value).replace(rePropName, function(match, number, quote, string) {
                                result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
                            });
                            return result;
                        }

                        var findLastIndex = createFindIndex(true);

                        function indexOf(array, value, fromIndex) {
                            var length = array ? array.length : 0;
                            if (!length) {
                                return -1;
                            }
                            if (typeof fromIndex == 'number') {
                                fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex;
                            } else if (fromIndex) {
                                var index = binaryIndex(array, value),
                                    other = array[index];

                                if (value === value ? (value === other) : (other !== other)) {
                                    return index;
                                }
                                return -1;
                            }
                            return baseIndexOf(array, value, fromIndex || 0);
                        }

                        function last(array) {
                            var length = array ? array.length : 0;
                            return length ? array[length - 1] : undefined;
                        }

                        function slice(array, start, end) {
                            var length = array ? array.length : 0;
                            if (!length) {
                                return [];
                            }
                            if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {
                                start = 0;
                                end = length;
                            }
                            return baseSlice(array, start, end);
                        }

                        function unzip(array) {
                            var index = -1,
                                length = (array && array.length && arrayMax(arrayMap(array, getLength))) >>> 0,
                                result = Array(length);

                            while (++index < length) {
                                result[index] = arrayMap(array, baseProperty(index));
                            }
                            return result;
                        }

                        var zip = restParam(unzip);

                        var forEach = createForEach(arrayEach, baseEach);

                        function includes(collection, target, fromIndex, guard) {
                            var length = collection ? getLength(collection) : 0;
                            if (!isLength(length)) {
                                collection = values(collection);
                                length = collection.length;
                            }
                            if (!length) {
                                return false;
                            }
                            if (typeof fromIndex != 'number' || (guard && isIterateeCall(target, fromIndex, guard))) {
                                fromIndex = 0;
                            } else {
                                fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0);
                            }
                            return (typeof collection == 'string' || !isArray(collection) && isString(collection)) ? (fromIndex < length && collection.indexOf(target, fromIndex) > -1) : (getIndexOf(collection, target, fromIndex) > -1);
                        }

                        function reject(collection, predicate, thisArg) {
                            var func = isArray(collection) ? arrayFilter : baseFilter;
                            predicate = getCallback(predicate, thisArg, 3);
                            return func(collection, function(value, index, collection) {
                                return !predicate(value, index, collection);
                            });
                        }

                        function some(collection, predicate, thisArg) {
                            var func = isArray(collection) ? arraySome : baseSome;
                            if (thisArg && isIterateeCall(collection, predicate, thisArg)) {
                                predicate = null;
                            }
                            if (typeof predicate != 'function' || thisArg !== undefined) {
                                predicate = getCallback(predicate, thisArg, 3);
                            }
                            return func(collection, predicate);
                        }

                        function restParam(func, start) {
                            if (typeof func != 'function') {
                                throw new TypeError(FUNC_ERROR_TEXT);
                            }
                            start = nativeMax(start === undefined ? (func.length - 1) : (+start || 0), 0);
                            return function() {
                                var args = arguments,
                                    index = -1,
                                    length = nativeMax(args.length - start, 0),
                                    rest = Array(length);

                                while (++index < length) {
                                    rest[index] = args[start + index];
                                }
                                switch (start) {
                                    case 0:
                                        return func.call(this, rest);
                                    case 1:
                                        return func.call(this, args[0], rest);
                                    case 2:
                                        return func.call(this, args[0], args[1], rest);
                                }
                                var otherArgs = Array(start + 1);
                                index = -1;
                                while (++index < start) {
                                    otherArgs[index] = args[index];
                                }
                                otherArgs[start] = rest;
                                return func.apply(this, otherArgs);
                            };
                        }

                        function clone(value, isDeep, customizer, thisArg) {
                            if (isDeep && typeof isDeep != 'boolean' && isIterateeCall(value, isDeep, customizer)) {
                                isDeep = false;
                            } else if (typeof isDeep == 'function') {
                                thisArg = customizer;
                                customizer = isDeep;
                                isDeep = false;
                            }
                            customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 1);
                            return baseClone(value, isDeep, customizer);
                        }

                        function isArguments(value) {
                            var length = isObjectLike(value) ? value.length : undefined;
                            return isLength(length) && objToString.call(value) == argsTag;
                        }

                        var isArray = nativeIsArray || function(value) {
                            return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag;
                        };

                        function isEmpty(value) {
                            if (value == null) {
                                return true;
                            }
                            var length = getLength(value);
                            if (isLength(length) && (isArray(value) || isString(value) || isArguments(value) ||
                                    (isObjectLike(value) && isFunction(value.splice)))) {
                                return !length;
                            }
                            return !keys(value).length;
                        }

                        var isFunction = !(baseIsFunction(/x/) || (Uint8Array && !baseIsFunction(Uint8Array))) ? baseIsFunction : function(value) {
                            return objToString.call(value) == funcTag;
                        };

                        function isObject(value) {
                            var type = typeof value;
                            return type == 'function' || (!!value && type == 'object');
                        }

                        function isNative(value) {
                            if (value == null) {
                                return false;
                            }
                            if (objToString.call(value) == funcTag) {
                                return reIsNative.test(fnToString.call(value));
                            }
                            return isObjectLike(value) && reIsHostCtor.test(value);
                        }

                        function isNumber(value) {
                            return typeof value == 'number' || (isObjectLike(value) && objToString.call(value) == numberTag);
                        }

                        var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) {
                            if (!(value && objToString.call(value) == objectTag)) {
                                return false;
                            }
                            var valueOf = value.valueOf,
                                objProto = isNative(valueOf) && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto);

                            return objProto ? (value == objProto || getPrototypeOf(value) == objProto) : shimIsPlainObject(value);
                        };

                        function isString(value) {
                            return typeof value == 'string' || (isObjectLike(value) && objToString.call(value) == stringTag);
                        }

                        function isTypedArray(value) {
                            return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)];
                        }

                        function toPlainObject(value) {
                            return baseCopy(value, keysIn(value));
                        }

                        var assign = createAssigner(function(object, source, customizer) {
                            return customizer ? assignWith(object, source, customizer) : baseAssign(object, source);
                        });

                        function has(object, path) {
                            if (object == null) {
                                return false;
                            }
                            var result = hasOwnProperty.call(object, path);
                            if (!result && !isKey(path)) {
                                path = toPath(path);
                                object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));
                                path = last(path);
                                result = object != null && hasOwnProperty.call(object, path);
                            }
                            return result;
                        }

                        var keys = !nativeKeys ? shimKeys : function(object) {
                            if (object) {
                                var Ctor = object.constructor,
                                    length = object.length;
                            }
                            if ((typeof Ctor == 'function' && Ctor.prototype === object) ||
                                (typeof object != 'function' && isLength(length))) {
                                return shimKeys(object);
                            }
                            return isObject(object) ? nativeKeys(object) : [];
                        };

                        function keysIn(object) {
                            if (object == null) {
                                return [];
                            }
                            if (!isObject(object)) {
                                object = Object(object);
                            }
                            var length = object.length;
                            length = (length && isLength(length) &&
                                (isArray(object) || (support.nonEnumArgs && isArguments(object))) && length) || 0;

                            var Ctor = object.constructor,
                                index = -1,
                                isProto = typeof Ctor == 'function' && Ctor.prototype === object,
                                result = Array(length),
                                skipIndexes = length > 0;

                            while (++index < length) {
                                result[index] = (index + '');
                            }
                            for (var key in object) {
                                if (!(skipIndexes && isIndex(key, length)) &&
                                    !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
                                    result.push(key);
                                }
                            }
                            return result;
                        }

                        var merge = createAssigner(baseMerge);

                        function values(object) {
                            return baseValues(object, keys(object));
                        }

                        function escapeRegExp(string) {
                            string = baseToString(string);
                            return (string && reHasRegExpChars.test(string)) ? string.replace(reRegExpChars, '\\$&') : string;
                        }

                        function callback(func, thisArg, guard) {
                            if (guard && isIterateeCall(func, thisArg, guard)) {
                                thisArg = null;
                            }
                            return baseCallback(func, thisArg);
                        }

                        function constant(value) {
                            return function() {
                                return value;
                            };
                        }

                        function identity(value) {
                            return value;
                        }

                        function property(path) {
                            return isKey(path) ? baseProperty(path) : basePropertyDeep(path);
                        }
                        lodash.assign = assign;
                        lodash.callback = callback;
                        lodash.constant = constant;
                        lodash.forEach = forEach;
                        lodash.keys = keys;
                        lodash.keysIn = keysIn;
                        lodash.merge = merge;
                        lodash.property = property;
                        lodash.reject = reject;
                        lodash.restParam = restParam;
                        lodash.slice = slice;
                        lodash.toPlainObject = toPlainObject;
                        lodash.unzip = unzip;
                        lodash.values = values;
                        lodash.zip = zip;

                        lodash.each = forEach;
                        lodash.extend = assign;
                        lodash.iteratee = callback;
                        lodash.clone = clone;
                        lodash.escapeRegExp = escapeRegExp;
                        lodash.findLastIndex = findLastIndex;
                        lodash.has = has;
                        lodash.identity = identity;
                        lodash.includes = includes;
                        lodash.indexOf = indexOf;
                        lodash.isArguments = isArguments;
                        lodash.isArray = isArray;
                        lodash.isEmpty = isEmpty;
                        lodash.isFunction = isFunction;
                        lodash.isNative = isNative;
                        lodash.isNumber = isNumber;
                        lodash.isObject = isObject;
                        lodash.isPlainObject = isPlainObject;
                        lodash.isString = isString;
                        lodash.isTypedArray = isTypedArray;
                        lodash.last = last;
                        lodash.some = some;

                        lodash.any = some;
                        lodash.contains = includes;
                        lodash.include = includes;

                        lodash.VERSION = VERSION;
                        if (freeExports && freeModule) {
                            if (moduleExports) {
                                (freeModule.exports = lodash)._ = lodash;
                            } else {
                                freeExports._ = lodash;
                            }
                        } else {
                            root._ = lodash;
                        }
                    }.call(this));

                }).call(this, typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
            }, {}],
            "/node_modules/jshint/src/jshint.js": [function(_dereq_, module, exports) {

                var _ = _dereq_("../lodash");
                var events = _dereq_("events");
                var vars = _dereq_("./vars.js");
                var messages = _dereq_("./messages.js");
                var Lexer = _dereq_("./lex.js").Lexer;
                var reg = _dereq_("./reg.js");
                var state = _dereq_("./state.js").state;
                var style = _dereq_("./style.js");
                var options = _dereq_("./options.js");
                var scopeManager = _dereq_("./scope-manager.js");

                var JSHINT = (function() {
                    "use strict";

                    var api, // Extension API
                        bang = {
                            "<": true,
                            "<=": true,
                            "==": true,
                            "===": true,
                            "!==": true,
                            "!=": true,
                            ">": true,
                            ">=": true,
                            "+": true,
                            "-": true,
                            "*": true,
                            "/": true,
                            "%": true
                        },

                        declared, // Globals that were declared using /*global ... */ syntax.

                        functionicity = [
                            "closure", "exception", "global", "label",
                            "outer", "unused", "var"
                        ],

                        functions, // All of the functions

                        inblock,
                        indent,
                        lookahead,
                        lex,
                        member,
                        membersOnly,
                        predefined, // Global variables defined by option

                        stack,
                        urls,

                        extraModules = [],
                        emitter = new events.EventEmitter();

                    function checkOption(name, t) {
                        name = name.trim();

                        if (/^[+-]W\d{3}$/g.test(name)) {
                            return true;
                        }

                        if (options.validNames.indexOf(name) === -1) {
                            if (t.type !== "jslint" && !_.has(options.removed, name)) {
                                error("E001", t, name);
                                return false;
                            }
                        }

                        return true;
                    }

                    function isString(obj) {
                        return Object.prototype.toString.call(obj) === "[object String]";
                    }

                    function isIdentifier(tkn, value) {
                        if (!tkn)
                            return false;

                        if (!tkn.identifier || tkn.value !== value)
                            return false;

                        return true;
                    }

                    function isReserved(token) {
                        if (!token.reserved) {
                            return false;
                        }
                        var meta = token.meta;

                        if (meta && meta.isFutureReservedWord && state.inES5()) {
                            if (!meta.es5) {
                                return false;
                            }
                            if (meta.strictOnly) {
                                if (!state.option.strict && !state.isStrict()) {
                                    return false;
                                }
                            }

                            if (token.isProperty) {
                                return false;
                            }
                        }

                        return true;
                    }

                    function supplant(str, data) {
                        return str.replace(/\{([^{}]*)\}/g, function(a, b) {
                            var r = data[b];
                            return typeof r === "string" || typeof r === "number" ? r : a;
                        });
                    }

                    function combine(dest, src) {
                        Object.keys(src).forEach(function(name) {
                            if (_.has(JSHINT.blacklist, name)) return;
                            dest[name] = src[name];
                        });
                    }

                    function processenforceall() {
                        if (state.option.enforceall) {
                            for (var enforceopt in options.bool.enforcing) {
                                if (state.option[enforceopt] === undefined &&
                                    !options.noenforceall[enforceopt]) {
                                    state.option[enforceopt] = true;
                                }
                            }
                            for (var relaxopt in options.bool.relaxing) {
                                if (state.option[relaxopt] === undefined) {
                                    state.option[relaxopt] = false;
                                }
                            }
                        }
                    }

                    function assume() {
                        processenforceall();
                        if (!state.option.esversion && !state.option.moz) {
                            if (state.option.es3) {
                                state.option.esversion = 3;
                            } else if (state.option.esnext) {
                                state.option.esversion = 6;
                            } else {
                                state.option.esversion = 5;
                            }
                        }

                        if (state.inES5()) {
                            combine(predefined, vars.ecmaIdentifiers[5]);
                        }

                        if (state.inES6()) {
                            combine(predefined, vars.ecmaIdentifiers[6]);
                        }

                        if (state.option.module) {
                            if (state.option.strict === true) {
                                state.option.strict = "global";
                            }
                            if (!state.inES6()) {
                                warning("W134", state.tokens.next, "module", 6);
                            }
                        }

                        if (state.option.couch) {
                            combine(predefined, vars.couch);
                        }

                        if (state.option.qunit) {
                            combine(predefined, vars.qunit);
                        }

                        if (state.option.rhino) {
                            combine(predefined, vars.rhino);
                        }

                        if (state.option.shelljs) {
                            combine(predefined, vars.shelljs);
                            combine(predefined, vars.node);
                        }
                        if (state.option.typed) {
                            combine(predefined, vars.typed);
                        }

                        if (state.option.phantom) {
                            combine(predefined, vars.phantom);
                            if (state.option.strict === true) {
                                state.option.strict = "global";
                            }
                        }

                        if (state.option.prototypejs) {
                            combine(predefined, vars.prototypejs);
                        }

                        if (state.option.node) {
                            combine(predefined, vars.node);
                            combine(predefined, vars.typed);
                            if (state.option.strict === true) {
                                state.option.strict = "global";
                            }
                        }

                        if (state.option.devel) {
                            combine(predefined, vars.devel);
                        }

                        if (state.option.dojo) {
                            combine(predefined, vars.dojo);
                        }

                        if (state.option.browser) {
                            combine(predefined, vars.browser);
                            combine(predefined, vars.typed);
                        }

                        if (state.option.browserify) {
                            combine(predefined, vars.browser);
                            combine(predefined, vars.typed);
                            combine(predefined, vars.browserify);
                            if (state.option.strict === true) {
                                state.option.strict = "global";
                            }
                        }

                        if (state.option.nonstandard) {
                            combine(predefined, vars.nonstandard);
                        }

                        if (state.option.jasmine) {
                            combine(predefined, vars.jasmine);
                        }

                        if (state.option.jquery) {
                            combine(predefined, vars.jquery);
                        }

                        if (state.option.mootools) {
                            combine(predefined, vars.mootools);
                        }

                        if (state.option.worker) {
                            combine(predefined, vars.worker);
                        }

                        if (state.option.wsh) {
                            combine(predefined, vars.wsh);
                        }

                        if (state.option.globalstrict && state.option.strict !== false) {
                            state.option.strict = "global";
                        }

                        if (state.option.yui) {
                            combine(predefined, vars.yui);
                        }

                        if (state.option.mocha) {
                            combine(predefined, vars.mocha);
                        }
                    }

                    function quit(code, line, chr) {
                        var percentage = Math.floor((line / state.lines.length) * 100);
                        var message = messages.errors[code].desc;

                        throw {
                            name: "JSHintError",
                            line: line,
                            character: chr,
                            message: message + " (" + percentage + "% scanned).",
                            raw: message,
                            code: code
                        };
                    }

                    function removeIgnoredMessages() {
                        var ignored = state.ignoredLines;

                        if (_.isEmpty(ignored)) return;
                        JSHINT.errors = _.reject(JSHINT.errors, function(err) {
                            return ignored[err.line]
                        });
                    }

                    function warning(code, t, a, b, c, d) {
                        var ch, l, w, msg;

                        if (/^W\d{3}$/.test(code)) {
                            if (state.ignored[code])
                                return;

                            msg = messages.warnings[code];
                        } else if (/E\d{3}/.test(code)) {
                            msg = messages.errors[code];
                        } else if (/I\d{3}/.test(code)) {
                            msg = messages.info[code];
                        }

                        t = t || state.tokens.next || {};
                        if (t.id === "(end)") { // `~
                            t = state.tokens.curr;
                        }

                        l = t.line || 0;
                        ch = t.from || 0;

                        w = {
                            id: "(error)",
                            raw: msg.desc,
                            code: msg.code,
                            evidence: state.lines[l - 1] || "",
                            line: l,
                            character: ch,
                            scope: JSHINT.scope,
                            a: a,
                            b: b,
                            c: c,
                            d: d
                        };

                        w.reason = supplant(msg.desc, w);
                        JSHINT.errors.push(w);

                        removeIgnoredMessages();

                        if (JSHINT.errors.length >= state.option.maxerr)
                            quit("E043", l, ch);

                        return w;
                    }

                    function warningAt(m, l, ch, a, b, c, d) {
                        return warning(m, {
                            line: l,
                            from: ch
                        }, a, b, c, d);
                    }

                    function error(m, t, a, b, c, d) {
                        warning(m, t, a, b, c, d);
                    }

                    function errorAt(m, l, ch, a, b, c, d) {
                        return error(m, {
                            line: l,
                            from: ch
                        }, a, b, c, d);
                    }

                    function addInternalSrc(elem, src) {
                        var i;
                        i = {
                            id: "(internal)",
                            elem: elem,
                            value: src
                        };
                        JSHINT.internals.push(i);
                        return i;
                    }

                    function doOption() {
                        var nt = state.tokens.next;
                        var body = nt.body.match(/(-\s+)?[^\s,:]+(?:\s*:\s*(-\s+)?[^\s,]+)?/g) || [];

                        var predef = {};
                        if (nt.type === "globals") {
                            body.forEach(function(g, idx) {
                                g = g.split(":");
                                var key = (g[0] || "").trim();
                                var val = (g[1] || "").trim();

                                if (key === "-" || !key.length) {
                                    if (idx > 0 && idx === body.length - 1) {
                                        return;
                                    }
                                    error("E002", nt);
                                    return;
                                }

                                if (key.charAt(0) === "-") {
                                    key = key.slice(1);
                                    val = false;

                                    JSHINT.blacklist[key] = key;
                                    delete predefined[key];
                                } else {
                                    predef[key] = (val === "true");
                                }
                            });

                            combine(predefined, predef);

                            for (var key in predef) {
                                if (_.has(predef, key)) {
                                    declared[key] = nt;
                                }
                            }
                        }

                        if (nt.type === "exported") {
                            body.forEach(function(e, idx) {
                                if (!e.length) {
                                    if (idx > 0 && idx === body.length - 1) {
                                        return;
                                    }
                                    error("E002", nt);
                                    return;
                                }

                                state.funct["(scope)"].addExported(e);
                            });
                        }

                        if (nt.type === "members") {
                            membersOnly = membersOnly || {};

                            body.forEach(function(m) {
                                var ch1 = m.charAt(0);
                                var ch2 = m.charAt(m.length - 1);

                                if (ch1 === ch2 && (ch1 === "\"" || ch1 === "'")) {
                                    m = m
                                        .substr(1, m.length - 2)
                                        .replace("\\\"", "\"");
                                }

                                membersOnly[m] = false;
                            });
                        }

                        var numvals = [
                            "maxstatements",
                            "maxparams",
                            "maxdepth",
                            "maxcomplexity",
                            "maxerr",
                            "maxlen",
                            "indent"
                        ];

                        if (nt.type === "jshint" || nt.type === "jslint") {
                            body.forEach(function(g) {
                                g = g.split(":");
                                var key = (g[0] || "").trim();
                                var val = (g[1] || "").trim();

                                if (!checkOption(key, nt)) {
                                    return;
                                }

                                if (numvals.indexOf(key) >= 0) {
                                    if (val !== "false") {
                                        val = +val;

                                        if (typeof val !== "number" || !isFinite(val) || val <= 0 || Math.floor(val) !== val) {
                                            error("E032", nt, g[1].trim());
                                            return;
                                        }

                                        state.option[key] = val;
                                    } else {
                                        state.option[key] = key === "indent" ? 4 : false;
                                    }

                                    return;
                                }

                                if (key === "validthis") {

                                    if (state.funct["(global)"])
                                        return void error("E009");

                                    if (val !== "true" && val !== "false")
                                        return void error("E002", nt);

                                    state.option.validthis = (val === "true");
                                    return;
                                }

                                if (key === "quotmark") {
                                    switch (val) {
                                        case "true":
                                        case "false":
                                            state.option.quotmark = (val === "true");
                                            break;
                                        case "double":
                                        case "single":
                                            state.option.quotmark = val;
                                            break;
                                        default:
                                            error("E002", nt);
                                    }
                                    return;
                                }

                                if (key === "shadow") {
                                    switch (val) {
                                        case "true":
                                            state.option.shadow = true;
                                            break;
                                        case "outer":
                                            state.option.shadow = "outer";
                                            break;
                                        case "false":
                                        case "inner":
                                            state.option.shadow = "inner";
                                            break;
                                        default:
                                            error("E002", nt);
                                    }
                                    return;
                                }

                                if (key === "unused") {
                                    switch (val) {
                                        case "true":
                                            state.option.unused = true;
                                            break;
                                        case "false":
                                            state.option.unused = false;
                                            break;
                                        case "vars":
                                        case "strict":
                                            state.option.unused = val;
                                            break;
                                        default:
                                            error("E002", nt);
                                    }
                                    return;
                                }

                                if (key === "latedef") {
                                    switch (val) {
                                        case "true":
                                            state.option.latedef = true;
                                            break;
                                        case "false":
                                            state.option.latedef = false;
                                            break;
                                        case "nofunc":
                                            state.option.latedef = "nofunc";
                                            break;
                                        default:
                                            error("E002", nt);
                                    }
                                    return;
                                }

                                if (key === "ignore") {
                                    switch (val) {
                                        case "line":
                                            state.ignoredLines[nt.line] = true;
                                            removeIgnoredMessages();
                                            break;
                                        default:
                                            error("E002", nt);
                                    }
                                    return;
                                }

                                if (key === "strict") {
                                    switch (val) {
                                        case "true":
                                            state.option.strict = true;
                                            break;
                                        case "false":
                                            state.option.strict = false;
                                            break;
                                        case "func":
                                        case "global":
                                        case "implied":
                                            state.option.strict = val;
                                            break;
                                        default:
                                            error("E002", nt);
                                    }
                                    return;
                                }

                                if (key === "module") {
                                    if (!hasParsedCode(state.funct)) {
                                        error("E055", state.tokens.next, "module");
                                    }
                                }
                                var esversions = {
                                    es3: 3,
                                    es5: 5,
                                    esnext: 6
                                };
                                if (_.has(esversions, key)) {
                                    switch (val) {
                                        case "true":
                                            state.option.moz = false;
                                            state.option.esversion = esversions[key];
                                            break;
                                        case "false":
                                            if (!state.option.moz) {
                                                state.option.esversion = 5;
                                            }
                                            break;
                                        default:
                                            error("E002", nt);
                                    }
                                    return;
                                }

                                if (key === "esversion") {
                                    switch (val) {
                                        case "5":
                                            if (state.inES5(true)) {
                                                warning("I003");
                                            }
                                        case "3":
                                        case "6":
                                            state.option.moz = false;
                                            state.option.esversion = +val;
                                            break;
                                        case "2015":
                                            state.option.moz = false;
                                            state.option.esversion = 6;
                                            break;
                                        default:
                                            error("E002", nt);
                                    }
                                    if (!hasParsedCode(state.funct)) {
                                        error("E055", state.tokens.next, "esversion");
                                    }
                                    return;
                                }

                                var match = /^([+-])(W\d{3})$/g.exec(key);
                                if (match) {
                                    state.ignored[match[2]] = (match[1] === "-");
                                    return;
                                }

                                var tn;
                                if (val === "true" || val === "false") {
                                    if (nt.type === "jslint") {
                                        tn = options.renamed[key] || key;
                                        state.option[tn] = (val === "true");

                                        if (options.inverted[tn] !== undefined) {
                                            state.option[tn] = !state.option[tn];
                                        }
                                    } else {
                                        state.option[key] = (val === "true");
                                    }

                                    if (key === "newcap") {
                                        state.option["(explicitNewcap)"] = true;
                                    }
                                    return;
                                }

                                error("E002", nt);
                            });

                            assume();
                        }
                    }

                    function peek(p) {
                        var i = p || 0,
                            j = lookahead.length,
                            t;

                        if (i < j) {
                            return lookahead[i];
                        }

                        while (j <= i) {
                            t = lookahead[j];
                            if (!t) {
                                t = lookahead[j] = lex.token();
                            }
                            j += 1;
                        }
                        if (!t && state.tokens.next.id === "(end)") {
                            return state.tokens.next;
                        }

                        return t;
                    }

                    function peekIgnoreEOL() {
                        var i = 0;
                        var t;
                        do {
                            t = peek(i++);
                        } while (t.id === "(endline)");
                        return t;
                    }

                    function advance(id, t) {

                        switch (state.tokens.curr.id) {
                            case "(number)":
                                if (state.tokens.next.id === ".") {
                                    warning("W005", state.tokens.curr);
                                }
                                break;
                            case "-":
                                if (state.tokens.next.id === "-" || state.tokens.next.id === "--") {
                                    warning("W006");
                                }
                                break;
                            case "+":
                                if (state.tokens.next.id === "+" || state.tokens.next.id === "++") {
                                    warning("W007");
                                }
                                break;
                        }

                        if (id && state.tokens.next.id !== id) {
                            if (t) {
                                if (state.tokens.next.id === "(end)") {
                                    error("E019", t, t.id);
                                } else {
                                    error("E020", state.tokens.next, id, t.id, t.line, state.tokens.next.value);
                                }
                            } else if (state.tokens.next.type !== "(identifier)" || state.tokens.next.value !== id) {
                                warning("W116", state.tokens.next, id, state.tokens.next.value);
                            }
                        }

                        state.tokens.prev = state.tokens.curr;
                        state.tokens.curr = state.tokens.next;
                        for (;;) {
                            state.tokens.next = lookahead.shift() || lex.token();

                            if (!state.tokens.next) { // No more tokens left, give up
                                quit("E041", state.tokens.curr.line);
                            }

                            if (state.tokens.next.id === "(end)" || state.tokens.next.id === "(error)") {
                                return;
                            }

                            if (state.tokens.next.check) {
                                state.tokens.next.check();
                            }

                            if (state.tokens.next.isSpecial) {
                                if (state.tokens.next.type === "falls through") {
                                    state.tokens.curr.caseFallsThrough = true;
                                } else {
                                    doOption();
                                }
                            } else {
                                if (state.tokens.next.id !== "(endline)") {
                                    break;
                                }
                            }
                        }
                    }

                    function isInfix(token) {
                        return token.infix || (!token.identifier && !token.template && !!token.led);
                    }

                    function isEndOfExpr() {
                        var curr = state.tokens.curr;
                        var next = state.tokens.next;
                        if (next.id === ";" || next.id === "}" || next.id === ":") {
                            return true;
                        }
                        if (isInfix(next) === isInfix(curr) || (curr.id === "yield" && state.inMoz())) {
                            return curr.line !== startLine(next);
                        }
                        return false;
                    }

                    function isBeginOfExpr(prev) {
                        return !prev.left && prev.arity !== "unary";
                    }

                    function expression(rbp, initial) {
                        var left, isArray = false,
                            isObject = false,
                            isLetExpr = false;

                        state.nameStack.push();
                        if (!initial && state.tokens.next.value === "let" && peek(0).value === "(") {
                            if (!state.inMoz()) {
                                warning("W118", state.tokens.next, "let expressions");
                            }
                            isLetExpr = true;
                            state.funct["(scope)"].stack();
                            advance("let");
                            advance("(");
                            state.tokens.prev.fud();
                            advance(")");
                        }

                        if (state.tokens.next.id === "(end)")
                            error("E006", state.tokens.curr);

                        var isDangerous =
                            state.option.asi &&
                            state.tokens.prev.line !== startLine(state.tokens.curr) &&
                            _.contains(["]", ")"], state.tokens.prev.id) &&
                            _.contains(["[", "("], state.tokens.curr.id);

                        if (isDangerous)
                            warning("W014", state.tokens.curr, state.tokens.curr.id);

                        advance();

                        if (initial) {
                            state.funct["(verb)"] = state.tokens.curr.value;
                            state.tokens.curr.beginsStmt = true;
                        }

                        if (initial === true && state.tokens.curr.fud) {
                            left = state.tokens.curr.fud();
                        } else {
                            if (state.tokens.curr.nud) {
                                left = state.tokens.curr.nud();
                            } else {
                                error("E030", state.tokens.curr, state.tokens.curr.id);
                            }
                            while ((rbp < state.tokens.next.lbp || state.tokens.next.type === "(template)") &&
                                !isEndOfExpr()) {
                                isArray = state.tokens.curr.value === "Array";
                                isObject = state.tokens.curr.value === "Object";
                                if (left && (left.value || (left.first && left.first.value))) {
                                    if (left.value !== "new" ||
                                        (left.first && left.first.value && left.first.value === ".")) {
                                        isArray = false;
                                        if (left.value !== state.tokens.curr.value) {
                                            isObject = false;
                                        }
                                    }
                                }

                                advance();

                                if (isArray && state.tokens.curr.id === "(" && state.tokens.next.id === ")") {
                                    warning("W009", state.tokens.curr);
                                }

                                if (isObject && state.tokens.curr.id === "(" && state.tokens.next.id === ")") {
                                    warning("W010", state.tokens.curr);
                                }

                                if (left && state.tokens.curr.led) {
                                    left = state.tokens.curr.led(left);
                                } else {
                                    error("E033", state.tokens.curr, state.tokens.curr.id);
                                }
                            }
                        }
                        if (isLetExpr) {
                            state.funct["(scope)"].unstack();
                        }

                        state.nameStack.pop();

                        return left;
                    }

                    function startLine(token) {
                        return token.startLine || token.line;
                    }

                    function nobreaknonadjacent(left, right) {
                        left = left || state.tokens.curr;
                        right = right || state.tokens.next;
                        if (!state.option.laxbreak && left.line !== startLine(right)) {
                            warning("W014", right, right.value);
                        }
                    }

                    function nolinebreak(t) {
                        t = t || state.tokens.curr;
                        if (t.line !== startLine(state.tokens.next)) {
                            warning("E022", t, t.value);
                        }
                    }

                    function nobreakcomma(left, right) {
                        if (left.line !== startLine(right)) {
                            if (!state.option.laxcomma) {
                                if (comma.first) {
                                    warning("I001");
                                    comma.first = false;
                                }
                                warning("W014", left, right.value);
                            }
                        }
                    }

                    function comma(opts) {
                        opts = opts || {};

                        if (!opts.peek) {
                            nobreakcomma(state.tokens.curr, state.tokens.next);
                            advance(",");
                        } else {
                            nobreakcomma(state.tokens.prev, state.tokens.curr);
                        }

                        if (state.tokens.next.identifier && !(opts.property && state.inES5())) {
                            switch (state.tokens.next.value) {
                                case "break":
                                case "case":
                                case "catch":
                                case "continue":
                                case "default":
                                case "do":
                                case "else":
                                case "finally":
                                case "for":
                                case "if":
                                case "in":
                                case "instanceof":
                                case "return":
                                case "switch":
                                case "throw":
                                case "try":
                                case "var":
                                case "let":
                                case "while":
                                case "with":
                                    error("E024", state.tokens.next, state.tokens.next.value);
                                    return false;
                            }
                        }

                        if (state.tokens.next.type === "(punctuator)") {
                            switch (state.tokens.next.value) {
                                case "}":
                                case "]":
                                case ",":
                                    if (opts.allowTrailing) {
                                        return true;
                                    }
                                case ")":
                                    error("E024", state.tokens.next, state.tokens.next.value);
                                    return false;
                            }
                        }
                        return true;
                    }

                    function symbol(s, p) {
                        var x = state.syntax[s];
                        if (!x || typeof x !== "object") {
                            state.syntax[s] = x = {
                                id: s,
                                lbp: p,
                                value: s
                            };
                        }
                        return x;
                    }

                    function delim(s) {
                        var x = symbol(s, 0);
                        x.delim = true;
                        return x;
                    }

                    function stmt(s, f) {
                        var x = delim(s);
                        x.identifier = x.reserved = true;
                        x.fud = f;
                        return x;
                    }

                    function blockstmt(s, f) {
                        var x = stmt(s, f);
                        x.block = true;
                        return x;
                    }

                    function reserveName(x) {
                        var c = x.id.charAt(0);
                        if ((c >= "a" && c <= "z") || (c >= "A" && c <= "Z")) {
                            x.identifier = x.reserved = true;
                        }
                        return x;
                    }

                    function prefix(s, f) {
                        var x = symbol(s, 150);
                        reserveName(x);

                        x.nud = (typeof f === "function") ? f : function() {
                            this.arity = "unary";
                            this.right = expression(150);

                            if (this.id === "++" || this.id === "--") {
                                if (state.option.plusplus) {
                                    warning("W016", this, this.id);
                                } else if (this.right && (!this.right.identifier || isReserved(this.right)) &&
                                    this.right.id !== "." && this.right.id !== "[") {
                                    warning("W017", this);
                                }

                                if (this.right && this.right.isMetaProperty) {
                                    error("E031", this);
                                } else if (this.right && this.right.identifier) {
                                    state.funct["(scope)"].block.modify(this.right.value, this);
                                }
                            }

                            return this;
                        };

                        return x;
                    }

                    function type(s, f) {
                        var x = delim(s);
                        x.type = s;
                        x.nud = f;
                        return x;
                    }

                    function reserve(name, func) {
                        var x = type(name, func);
                        x.identifier = true;
                        x.reserved = true;
                        return x;
                    }

                    function FutureReservedWord(name, meta) {
                        var x = type(name, (meta && meta.nud) || function() {
                            return this;
                        });

                        meta = meta || {};
                        meta.isFutureReservedWord = true;

                        x.value = name;
                        x.identifier = true;
                        x.reserved = true;
                        x.meta = meta;

                        return x;
                    }

                    function reservevar(s, v) {
                        return reserve(s, function() {
                            if (typeof v === "function") {
                                v(this);
                            }
                            return this;
                        });
                    }

                    function infix(s, f, p, w) {
                        var x = symbol(s, p);
                        reserveName(x);
                        x.infix = true;
                        x.led = function(left) {
                            if (!w) {
                                nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
                            }
                            if ((s === "in" || s === "instanceof") && left.id === "!") {
                                warning("W018", left, "!");
                            }
                            if (typeof f === "function") {
                                return f(left, this);
                            } else {
                                this.left = left;
                                this.right = expression(p);
                                return this;
                            }
                        };
                        return x;
                    }

                    function application(s) {
                        var x = symbol(s, 42);

                        x.led = function(left) {
                            nobreaknonadjacent(state.tokens.prev, state.tokens.curr);

                            this.left = left;
                            this.right = doFunction({
                                type: "arrow",
                                loneArg: left
                            });
                            return this;
                        };
                        return x;
                    }

                    function relation(s, f) {
                        var x = symbol(s, 100);

                        x.led = function(left) {
                            nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
                            this.left = left;
                            var right = this.right = expression(100);

                            if (isIdentifier(left, "NaN") || isIdentifier(right, "NaN")) {
                                warning("W019", this);
                            } else if (f) {
                                f.apply(this, [left, right]);
                            }

                            if (!left || !right) {
                                quit("E041", state.tokens.curr.line);
                            }

                            if (left.id === "!") {
                                warning("W018", left, "!");
                            }

                            if (right.id === "!") {
                                warning("W018", right, "!");
                            }

                            return this;
                        };
                        return x;
                    }

                    function isPoorRelation(node) {
                        return node &&
                            ((node.type === "(number)" && +node.value === 0) ||
                                (node.type === "(string)" && node.value === "") ||
                                (node.type === "null" && !state.option.eqnull) ||
                                node.type === "true" ||
                                node.type === "false" ||
                                node.type === "undefined");
                    }

                    var typeofValues = {};
                    typeofValues.legacy = [
                        "xml",
                        "unknown"
                    ];
                    typeofValues.es3 = [
                        "undefined", "boolean", "number", "string", "function", "object",
                    ];
                    typeofValues.es3 = typeofValues.es3.concat(typeofValues.legacy);
                    typeofValues.es6 = typeofValues.es3.concat("symbol");

                    function isTypoTypeof(left, right, state) {
                        var values;

                        if (state.option.notypeof)
                            return false;

                        if (!left || !right)
                            return false;

                        values = state.inES6() ? typeofValues.es6 : typeofValues.es3;

                        if (right.type === "(identifier)" && right.value === "typeof" && left.type === "(string)")
                            return !_.contains(values, left.value);

                        return false;
                    }

                    function isGlobalEval(left, state) {
                        var isGlobal = false;
                        if (left.type === "this" && state.funct["(context)"] === null) {
                            isGlobal = true;
                        } else if (left.type === "(identifier)") {
                            if (state.option.node && left.value === "global") {
                                isGlobal = true;
                            } else if (state.option.browser && (left.value === "window" || left.value === "document")) {
                                isGlobal = true;
                            }
                        }

                        return isGlobal;
                    }

                    function findNativePrototype(left) {
                        var natives = [
                            "Array", "ArrayBuffer", "Boolean", "Collator", "DataView", "Date",
                            "DateTimeFormat", "Error", "EvalError", "Float32Array", "Float64Array",
                            "Function", "Infinity", "Intl", "Int16Array", "Int32Array", "Int8Array",
                            "Iterator", "Number", "NumberFormat", "Object", "RangeError",
                            "ReferenceError", "RegExp", "StopIteration", "String", "SyntaxError",
                            "TypeError", "Uint16Array", "Uint32Array", "Uint8Array", "Uint8ClampedArray",
                            "URIError"
                        ];

                        function walkPrototype(obj) {
                            if (typeof obj !== "object") return;
                            return obj.right === "prototype" ? obj : walkPrototype(obj.left);
                        }

                        function walkNative(obj) {
                            while (!obj.identifier && typeof obj.left === "object")
                                obj = obj.left;

                            if (obj.identifier && natives.indexOf(obj.value) >= 0)
                                return obj.value;
                        }

                        var prototype = walkPrototype(left);
                        if (prototype) return walkNative(prototype);
                    }

                    function checkLeftSideAssign(left, assignToken, options) {

                        var allowDestructuring = options && options.allowDestructuring;

                        assignToken = assignToken || left;

                        if (state.option.freeze) {
                            var nativeObject = findNativePrototype(left);
                            if (nativeObject)
                                warning("W121", left, nativeObject);
                        }

                        if (left.identifier && !left.isMetaProperty) {
                            state.funct["(scope)"].block.reassign(left.value, left);
                        }

                        if (left.id === ".") {
                            if (!left.left || left.left.value === "arguments" && !state.isStrict()) {
                                warning("E031", assignToken);
                            }

                            state.nameStack.set(state.tokens.prev);
                            return true;
                        } else if (left.id === "{" || left.id === "[") {
                            if (allowDestructuring && state.tokens.curr.left.destructAssign) {
                                state.tokens.curr.left.destructAssign.forEach(function(t) {
                                    if (t.id) {
                                        state.funct["(scope)"].block.modify(t.id, t.token);
                                    }
                                });
                            } else {
                                if (left.id === "{" || !left.left) {
                                    warning("E031", assignToken);
                                } else if (left.left.value === "arguments" && !state.isStrict()) {
                                    warning("E031", assignToken);
                                }
                            }

                            if (left.id === "[") {
                                state.nameStack.set(left.right);
                            }

                            return true;
                        } else if (left.isMetaProperty) {
                            error("E031", assignToken);
                            return true;
                        } else if (left.identifier && !isReserved(left)) {
                            if (state.funct["(scope)"].labeltype(left.value) === "exception") {
                                warning("W022", left);
                            }
                            state.nameStack.set(left);
                            return true;
                        }

                        if (left === state.syntax["function"]) {
                            warning("W023", state.tokens.curr);
                        }

                        return false;
                    }

                    function assignop(s, f, p) {
                        var x = infix(s, typeof f === "function" ? f : function(left, that) {
                            that.left = left;

                            if (left && checkLeftSideAssign(left, that, {
                                    allowDestructuring: true
                                })) {
                                that.right = expression(10);
                                return that;
                            }

                            error("E031", that);
                        }, p);

                        x.exps = true;
                        x.assign = true;
                        return x;
                    }


                    function bitwise(s, f, p) {
                        var x = symbol(s, p);
                        reserveName(x);
                        x.led = (typeof f === "function") ? f : function(left) {
                            if (state.option.bitwise) {
                                warning("W016", this, this.id);
                            }
                            this.left = left;
                            this.right = expression(p);
                            return this;
                        };
                        return x;
                    }

                    function bitwiseassignop(s) {
                        return assignop(s, function(left, that) {
                            if (state.option.bitwise) {
                                warning("W016", that, that.id);
                            }

                            if (left && checkLeftSideAssign(left, that)) {
                                that.right = expression(10);
                                return that;
                            }
                            error("E031", that);
                        }, 20);
                    }

                    function suffix(s) {
                        var x = symbol(s, 150);

                        x.led = function(left) {
                            if (state.option.plusplus) {
                                warning("W016", this, this.id);
                            } else if ((!left.identifier || isReserved(left)) && left.id !== "." && left.id !== "[") {
                                warning("W017", this);
                            }

                            if (left.isMetaProperty) {
                                error("E031", this);
                            } else if (left && left.identifier) {
                                state.funct["(scope)"].block.modify(left.value, left);
                            }

                            this.left = left;
                            return this;
                        };
                        return x;
                    }

                    function optionalidentifier(fnparam, prop, preserve) {
                        if (!state.tokens.next.identifier) {
                            return;
                        }

                        if (!preserve) {
                            advance();
                        }

                        var curr = state.tokens.curr;
                        var val = state.tokens.curr.value;

                        if (!isReserved(curr)) {
                            return val;
                        }

                        if (prop) {
                            if (state.inES5()) {
                                return val;
                            }
                        }

                        if (fnparam && val === "undefined") {
                            return val;
                        }

                        warning("W024", state.tokens.curr, state.tokens.curr.id);
                        return val;
                    }

                    function identifier(fnparam, prop) {
                        var i = optionalidentifier(fnparam, prop, false);
                        if (i) {
                            return i;
                        }
                        if (state.tokens.next.value === "...") {
                            if (!state.inES6(true)) {
                                warning("W119", state.tokens.next, "spread/rest operator", "6");
                            }
                            advance();

                            if (checkPunctuator(state.tokens.next, "...")) {
                                warning("E024", state.tokens.next, "...");
                                while (checkPunctuator(state.tokens.next, "...")) {
                                    advance();
                                }
                            }

                            if (!state.tokens.next.identifier) {
                                warning("E024", state.tokens.curr, "...");
                                return;
                            }

                            return identifier(fnparam, prop);
                        } else {
                            error("E030", state.tokens.next, state.tokens.next.value);
                            if (state.tokens.next.id !== ";") {
                                advance();
                            }
                        }
                    }


                    function reachable(controlToken) {
                        var i = 0,
                            t;
                        if (state.tokens.next.id !== ";" || controlToken.inBracelessBlock) {
                            return;
                        }
                        for (;;) {
                            do {
                                t = peek(i);
                                i += 1;
                            } while (t.id !== "(end)" && t.id === "(comment)");

                            if (t.reach) {
                                return;
                            }
                            if (t.id !== "(endline)") {
                                if (t.id === "function") {
                                    if (state.option.latedef === true) {
                                        warning("W026", t);
                                    }
                                    break;
                                }

                                warning("W027", t, t.value, controlToken.value);
                                break;
                            }
                        }
                    }

                    function parseFinalSemicolon() {
                        if (state.tokens.next.id !== ";") {
                            if (state.tokens.next.isUnclosed) return advance();

                            var sameLine = startLine(state.tokens.next) === state.tokens.curr.line &&
                                state.tokens.next.id !== "(end)";
                            var blockEnd = checkPunctuator(state.tokens.next, "}");

                            if (sameLine && !blockEnd) {
                                errorAt("E058", state.tokens.curr.line, state.tokens.curr.character);
                            } else if (!state.option.asi) {
                                if ((blockEnd && !state.option.lastsemic) || !sameLine) {
                                    warningAt("W033", state.tokens.curr.line, state.tokens.curr.character);
                                }
                            }
                        } else {
                            advance(";");
                        }
                    }

                    function statement() {
                        var i = indent,
                            r, t = state.tokens.next,
                            hasOwnScope = false;

                        if (t.id === ";") {
                            advance(";");
                            return;
                        }
                        var res = isReserved(t);

                        if (res && t.meta && t.meta.isFutureReservedWord && peek().id === ":") {
                            warning("W024", t, t.id);
                            res = false;
                        }

                        if (t.identifier && !res && peek().id === ":") {
                            advance();
                            advance(":");

                            hasOwnScope = true;
                            state.funct["(scope)"].stack();
                            state.funct["(scope)"].block.addBreakLabel(t.value, {
                                token: state.tokens.curr
                            });

                            if (!state.tokens.next.labelled && state.tokens.next.value !== "{") {
                                warning("W028", state.tokens.next, t.value, state.tokens.next.value);
                            }

                            state.tokens.next.label = t.value;
                            t = state.tokens.next;
                        }

                        if (t.id === "{") {
                            var iscase = (state.funct["(verb)"] === "case" && state.tokens.curr.value === ":");
                            block(true, true, false, false, iscase);
                            return;
                        }

                        r = expression(0, true);

                        if (r && !(r.identifier && r.value === "function") &&
                            !(r.type === "(punctuator)" && r.left &&
                                r.left.identifier && r.left.value === "function")) {
                            if (!state.isStrict() &&
                                state.option.strict === "global") {
                                warning("E007");
                            }
                        }

                        if (!t.block) {
                            if (!state.option.expr && (!r || !r.exps)) {
                                warning("W030", state.tokens.curr);
                            } else if (state.option.nonew && r && r.left && r.id === "(" && r.left.id === "new") {
                                warning("W031", t);
                            }
                            parseFinalSemicolon();
                        }

                        indent = i;
                        if (hasOwnScope) {
                            state.funct["(scope)"].unstack();
                        }
                        return r;
                    }


                    function statements() {
                        var a = [],
                            p;

                        while (!state.tokens.next.reach && state.tokens.next.id !== "(end)") {
                            if (state.tokens.next.id === ";") {
                                p = peek();

                                if (!p || (p.id !== "(" && p.id !== "[")) {
                                    warning("W032");
                                }

                                advance(";");
                            } else {
                                a.push(statement());
                            }
                        }
                        return a;
                    }

                    function directives() {
                        var i, p, pn;

                        while (state.tokens.next.id === "(string)") {
                            p = peek(0);
                            if (p.id === "(endline)") {
                                i = 1;
                                do {
                                    pn = peek(i++);
                                } while (pn.id === "(endline)");
                                if (pn.id === ";") {
                                    p = pn;
                                } else if (pn.value === "[" || pn.value === ".") {
                                    break;
                                } else if (!state.option.asi || pn.value === "(") {
                                    warning("W033", state.tokens.next);
                                }
                            } else if (p.id === "." || p.id === "[") {
                                break;
                            } else if (p.id !== ";") {
                                warning("W033", p);
                            }

                            advance();
                            var directive = state.tokens.curr.value;
                            if (state.directive[directive] ||
                                (directive === "use strict" && state.option.strict === "implied")) {
                                warning("W034", state.tokens.curr, directive);
                            }
                            state.directive[directive] = true;

                            if (p.id === ";") {
                                advance(";");
                            }
                        }

                        if (state.isStrict()) {
                            if (!state.option["(explicitNewcap)"]) {
                                state.option.newcap = true;
                            }
                            state.option.undef = true;
                        }
                    }

                    function block(ordinary, stmt, isfunc, isfatarrow, iscase) {
                        var a,
                            b = inblock,
                            old_indent = indent,
                            m,
                            t,
                            line,
                            d;

                        inblock = ordinary;

                        t = state.tokens.next;

                        var metrics = state.funct["(metrics)"];
                        metrics.nestedBlockDepth += 1;
                        metrics.verifyMaxNestedBlockDepthPerFunction();

                        if (state.tokens.next.id === "{") {
                            advance("{");
                            state.funct["(scope)"].stack();

                            line = state.tokens.curr.line;
                            if (state.tokens.next.id !== "}") {
                                indent += state.option.indent;
                                while (!ordinary && state.tokens.next.from > indent) {
                                    indent += state.option.indent;
                                }

                                if (isfunc) {
                                    m = {};
                                    for (d in state.directive) {
                                        if (_.has(state.directive, d)) {
                                            m[d] = state.directive[d];
                                        }
                                    }
                                    directives();

                                    if (state.option.strict && state.funct["(context)"]["(global)"]) {
                                        if (!m["use strict"] && !state.isStrict()) {
                                            warning("E007");
                                        }
                                    }
                                }

                                a = statements();

                                metrics.statementCount += a.length;

                                indent -= state.option.indent;
                            }

                            advance("}", t);

                            if (isfunc) {
                                state.funct["(scope)"].validateParams();
                                if (m) {
                                    state.directive = m;
                                }
                            }

                            state.funct["(scope)"].unstack();

                            indent = old_indent;
                        } else if (!ordinary) {
                            if (isfunc) {
                                state.funct["(scope)"].stack();

                                m = {};
                                if (stmt && !isfatarrow && !state.inMoz()) {
                                    error("W118", state.tokens.curr, "function closure expressions");
                                }

                                if (!stmt) {
                                    for (d in state.directive) {
                                        if (_.has(state.directive, d)) {
                                            m[d] = state.directive[d];
                                        }
                                    }
                                }
                                expression(10);

                                if (state.option.strict && state.funct["(context)"]["(global)"]) {
                                    if (!m["use strict"] && !state.isStrict()) {
                                        warning("E007");
                                    }
                                }

                                state.funct["(scope)"].unstack();
                            } else {
                                error("E021", state.tokens.next, "{", state.tokens.next.value);
                            }
                        } else {
                            state.funct["(noblockscopedvar)"] = state.tokens.next.id !== "for";
                            state.funct["(scope)"].stack();

                            if (!stmt || state.option.curly) {
                                warning("W116", state.tokens.next, "{", state.tokens.next.value);
                            }

                            state.tokens.next.inBracelessBlock = true;
                            indent += state.option.indent;
                            a = [statement()];
                            indent -= state.option.indent;

                            state.funct["(scope)"].unstack();
                            delete state.funct["(noblockscopedvar)"];
                        }
                        switch (state.funct["(verb)"]) {
                            case "break":
                            case "continue":
                            case "return":
                            case "throw":
                                if (iscase) {
                                    break;
                                }
                            default:
                                state.funct["(verb)"] = null;
                        }

                        inblock = b;
                        if (ordinary && state.option.noempty && (!a || a.length === 0)) {
                            warning("W035", state.tokens.prev);
                        }
                        metrics.nestedBlockDepth -= 1;
                        return a;
                    }


                    function countMember(m) {
                        if (membersOnly && typeof membersOnly[m] !== "boolean") {
                            warning("W036", state.tokens.curr, m);
                        }
                        if (typeof member[m] === "number") {
                            member[m] += 1;
                        } else {
                            member[m] = 1;
                        }
                    }

                    type("(number)", function() {
                        return this;
                    });

                    type("(string)", function() {
                        return this;
                    });

                    state.syntax["(identifier)"] = {
                        type: "(identifier)",
                        lbp: 0,
                        identifier: true,

                        nud: function() {
                            var v = this.value;
                            if (state.tokens.next.id === "=>") {
                                return this;
                            }

                            if (!state.funct["(comparray)"].check(v)) {
                                state.funct["(scope)"].block.use(v, state.tokens.curr);
                            }
                            return this;
                        },

                        led: function() {
                            error("E033", state.tokens.next, state.tokens.next.value);
                        }
                    };

                    var baseTemplateSyntax = {
                        lbp: 0,
                        identifier: false,
                        template: true,
                    };
                    state.syntax["(template)"] = _.extend({
                        type: "(template)",
                        nud: doTemplateLiteral,
                        led: doTemplateLiteral,
                        noSubst: false
                    }, baseTemplateSyntax);

                    state.syntax["(template middle)"] = _.extend({
                        type: "(template middle)",
                        middle: true,
                        noSubst: false
                    }, baseTemplateSyntax);

                    state.syntax["(template tail)"] = _.extend({
                        type: "(template tail)",
                        tail: true,
                        noSubst: false
                    }, baseTemplateSyntax);

                    state.syntax["(no subst template)"] = _.extend({
                        type: "(template)",
                        nud: doTemplateLiteral,
                        led: doTemplateLiteral,
                        noSubst: true,
                        tail: true // mark as tail, since it's always the last component
                    }, baseTemplateSyntax);

                    type("(regexp)", function() {
                        return this;
                    });

                    delim("(endline)");
                    delim("(begin)");
                    delim("(end)").reach = true;
                    delim("(error)").reach = true;
                    delim("}").reach = true;
                    delim(")");
                    delim("]");
                    delim("\"").reach = true;
                    delim("'").reach = true;
                    delim(";");
                    delim(":").reach = true;
                    delim("#");

                    reserve("else");
                    reserve("case").reach = true;
                    reserve("catch");
                    reserve("default").reach = true;
                    reserve("finally");
                    reservevar("arguments", function(x) {
                        if (state.isStrict() && state.funct["(global)"]) {
                            warning("E008", x);
                        }
                    });
                    reservevar("eval");
                    reservevar("false");
                    reservevar("Infinity");
                    reservevar("null");
                    reservevar("this", function(x) {
                        if (state.isStrict() && !isMethod() &&
                            !state.option.validthis && ((state.funct["(statement)"] &&
                                state.funct["(name)"].charAt(0) > "Z") || state.funct["(global)"])) {
                            warning("W040", x);
                        }
                    });
                    reservevar("true");
                    reservevar("undefined");

                    assignop("=", "assign", 20);
                    assignop("+=", "assignadd", 20);
                    assignop("-=", "assignsub", 20);
                    assignop("*=", "assignmult", 20);
                    assignop("/=", "assigndiv", 20).nud = function() {
                        error("E014");
                    };
                    assignop("%=", "assignmod", 20);

                    bitwiseassignop("&=");
                    bitwiseassignop("|=");
                    bitwiseassignop("^=");
                    bitwiseassignop("<<=");
                    bitwiseassignop(">>=");
                    bitwiseassignop(">>>=");
                    infix(",", function(left, that) {
                        var expr;
                        that.exprs = [left];

                        if (state.option.nocomma) {
                            warning("W127");
                        }

                        if (!comma({
                                peek: true
                            })) {
                            return that;
                        }
                        while (true) {
                            if (!(expr = expression(10))) {
                                break;
                            }
                            that.exprs.push(expr);
                            if (state.tokens.next.value !== "," || !comma()) {
                                break;
                            }
                        }
                        return that;
                    }, 10, true);

                    infix("?", function(left, that) {
                        increaseComplexityCount();
                        that.left = left;
                        that.right = expression(10);
                        advance(":");
                        that["else"] = expression(10);
                        return that;
                    }, 30);

                    var orPrecendence = 40;
                    infix("||", function(left, that) {
                        increaseComplexityCount();
                        that.left = left;
                        that.right = expression(orPrecendence);
                        return that;
                    }, orPrecendence);
                    infix("&&", "and", 50);
                    bitwise("|", "bitor", 70);
                    bitwise("^", "bitxor", 80);
                    bitwise("&", "bitand", 90);
                    relation("==", function(left, right) {
                        var eqnull = state.option.eqnull &&
                            ((left && left.value) === "null" || (right && right.value) === "null");

                        switch (true) {
                            case !eqnull && state.option.eqeqeq:
                                this.from = this.character;
                                warning("W116", this, "===", "==");
                                break;
                            case isPoorRelation(left):
                                warning("W041", this, "===", left.value);
                                break;
                            case isPoorRelation(right):
                                warning("W041", this, "===", right.value);
                                break;
                            case isTypoTypeof(right, left, state):
                                warning("W122", this, right.value);
                                break;
                            case isTypoTypeof(left, right, state):
                                warning("W122", this, left.value);
                                break;
                        }

                        return this;
                    });
                    relation("===", function(left, right) {
                        if (isTypoTypeof(right, left, state)) {
                            warning("W122", this, right.value);
                        } else if (isTypoTypeof(left, right, state)) {
                            warning("W122", this, left.value);
                        }
                        return this;
                    });
                    relation("!=", function(left, right) {
                        var eqnull = state.option.eqnull &&
                            ((left && left.value) === "null" || (right && right.value) === "null");

                        if (!eqnull && state.option.eqeqeq) {
                            this.from = this.character;
                            warning("W116", this, "!==", "!=");
                        } else if (isPoorRelation(left)) {
                            warning("W041", this, "!==", left.value);
                        } else if (isPoorRelation(right)) {
                            warning("W041", this, "!==", right.value);
                        } else if (isTypoTypeof(right, left, state)) {
                            warning("W122", this, right.value);
                        } else if (isTypoTypeof(left, right, state)) {
                            warning("W122", this, left.value);
                        }
                        return this;
                    });
                    relation("!==", function(left, right) {
                        if (isTypoTypeof(right, left, state)) {
                            warning("W122", this, right.value);
                        } else if (isTypoTypeof(left, right, state)) {
                            warning("W122", this, left.value);
                        }
                        return this;
                    });
                    relation("<");
                    relation(">");
                    relation("<=");
                    relation(">=");
                    bitwise("<<", "shiftleft", 120);
                    bitwise(">>", "shiftright", 120);
                    bitwise(">>>", "shiftrightunsigned", 120);
                    infix("in", "in", 120);
                    infix("instanceof", "instanceof", 120);
                    infix("+", function(left, that) {
                        var right;
                        that.left = left;
                        that.right = right = expression(130);

                        if (left && right && left.id === "(string)" && right.id === "(string)") {
                            left.value += right.value;
                            left.character = right.character;
                            if (!state.option.scripturl && reg.javascriptURL.test(left.value)) {
                                warning("W050", left);
                            }
                            return left;
                        }

                        return that;
                    }, 130);
                    prefix("+", "num");
                    prefix("+++", function() {
                        warning("W007");
                        this.arity = "unary";
                        this.right = expression(150);
                        return this;
                    });
                    infix("+++", function(left) {
                        warning("W007");
                        this.left = left;
                        this.right = expression(130);
                        return this;
                    }, 130);
                    infix("-", "sub", 130);
                    prefix("-", "neg");
                    prefix("---", function() {
                        warning("W006");
                        this.arity = "unary";
                        this.right = expression(150);
                        return this;
                    });
                    infix("---", function(left) {
                        warning("W006");
                        this.left = left;
                        this.right = expression(130);
                        return this;
                    }, 130);
                    infix("*", "mult", 140);
                    infix("/", "div", 140);
                    infix("%", "mod", 140);

                    suffix("++");
                    prefix("++", "preinc");
                    state.syntax["++"].exps = true;

                    suffix("--");
                    prefix("--", "predec");
                    state.syntax["--"].exps = true;
                    prefix("delete", function() {
                        var p = expression(10);
                        if (!p) {
                            return this;
                        }

                        if (p.id !== "." && p.id !== "[") {
                            warning("W051");
                        }
                        this.first = p;
                        if (p.identifier && !state.isStrict()) {
                            p.forgiveUndef = true;
                        }
                        return this;
                    }).exps = true;

                    prefix("~", function() {
                        if (state.option.bitwise) {
                            warning("W016", this, "~");
                        }
                        this.arity = "unary";
                        this.right = expression(150);
                        return this;
                    });

                    prefix("...", function() {
                        if (!state.inES6(true)) {
                            warning("W119", this, "spread/rest operator", "6");
                        }
                        if (!state.tokens.next.identifier &&
                            state.tokens.next.type !== "(string)" &&
                            !checkPunctuators(state.tokens.next, ["[", "("])) {

                            error("E030", state.tokens.next, state.tokens.next.value);
                        }
                        expression(150);
                        return this;
                    });

                    prefix("!", function() {
                        this.arity = "unary";
                        this.right = expression(150);

                        if (!this.right) { // '!' followed by nothing? Give up.
                            quit("E041", this.line || 0);
                        }

                        if (bang[this.right.id] === true) {
                            warning("W018", this, "!");
                        }
                        return this;
                    });

                    prefix("typeof", (function() {
                        var p = expression(150);
                        this.first = this.right = p;

                        if (!p) { // 'typeof' followed by nothing? Give up.
                            quit("E041", this.line || 0, this.character || 0);
                        }
                        if (p.identifier) {
                            p.forgiveUndef = true;
                        }
                        return this;
                    }));
                    prefix("new", function() {
                        var mp = metaProperty("target", function() {
                            if (!state.inES6(true)) {
                                warning("W119", state.tokens.prev, "new.target", "6");
                            }
                            var inFunction, c = state.funct;
                            while (c) {
                                inFunction = !c["(global)"];
                                if (!c["(arrow)"]) {
                                    break;
                                }
                                c = c["(context)"];
                            }
                            if (!inFunction) {
                                warning("W136", state.tokens.prev, "new.target");
                            }
                        });
                        if (mp) {
                            return mp;
                        }

                        var c = expression(155),
                            i;
                        if (c && c.id !== "function") {
                            if (c.identifier) {
                                c["new"] = true;
                                switch (c.value) {
                                    case "Number":
                                    case "String":
                                    case "Boolean":
                                    case "Math":
                                    case "JSON":
                                        warning("W053", state.tokens.prev, c.value);
                                        break;
                                    case "Symbol":
                                        if (state.inES6()) {
                                            warning("W053", state.tokens.prev, c.value);
                                        }
                                        break;
                                    case "Function":
                                        if (!state.option.evil) {
                                            warning("W054");
                                        }
                                        break;
                                    case "Date":
                                    case "RegExp":
                                    case "this":
                                        break;
                                    default:
                                        if (c.id !== "function") {
                                            i = c.value.substr(0, 1);
                                            if (state.option.newcap && (i < "A" || i > "Z") &&
                                                !state.funct["(scope)"].isPredefined(c.value)) {
                                                warning("W055", state.tokens.curr);
                                            }
                                        }
                                }
                            } else {
                                if (c.id !== "." && c.id !== "[" && c.id !== "(") {
                                    warning("W056", state.tokens.curr);
                                }
                            }
                        } else {
                            if (!state.option.supernew)
                                warning("W057", this);
                        }
                        if (state.tokens.next.id !== "(" && !state.option.supernew) {
                            warning("W058", state.tokens.curr, state.tokens.curr.value);
                        }
                        this.first = this.right = c;
                        return this;
                    });
                    state.syntax["new"].exps = true;

                    prefix("void").exps = true;

                    infix(".", function(left, that) {
                        var m = identifier(false, true);

                        if (typeof m === "string") {
                            countMember(m);
                        }

                        that.left = left;
                        that.right = m;

                        if (m && m === "hasOwnProperty" && state.tokens.next.value === "=") {
                            warning("W001");
                        }

                        if (left && left.value === "arguments" && (m === "callee" || m === "caller")) {
                            if (state.option.noarg)
                                warning("W059", left, m);
                            else if (state.isStrict())
                                error("E008");
                        } else if (!state.option.evil && left && left.value === "document" &&
                            (m === "write" || m === "writeln")) {
                            warning("W060", left);
                        }

                        if (!state.option.evil && (m === "eval" || m === "execScript")) {
                            if (isGlobalEval(left, state)) {
                                warning("W061");
                            }
                        }

                        return that;
                    }, 160, true);

                    infix("(", function(left, that) {
                        if (state.option.immed && left && !left.immed && left.id === "function") {
                            warning("W062");
                        }

                        var n = 0;
                        var p = [];

                        if (left) {
                            if (left.type === "(identifier)") {
                                if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) {
                                    if ("Array Number String Boolean Date Object Error Symbol".indexOf(left.value) === -1) {
                                        if (left.value === "Math") {
                                            warning("W063", left);
                                        } else if (state.option.newcap) {
                                            warning("W064", left);
                                        }
                                    }
                                }
                            }
                        }

                        if (state.tokens.next.id !== ")") {
                            for (;;) {
                                p[p.length] = expression(10);
                                n += 1;
                                if (state.tokens.next.id !== ",") {
                                    break;
                                }
                                comma();
                            }
                        }

                        advance(")");

                        if (typeof left === "object") {
                            if (!state.inES5() && left.value === "parseInt" && n === 1) {
                                warning("W065", state.tokens.curr);
                            }
                            if (!state.option.evil) {
                                if (left.value === "eval" || left.value === "Function" ||
                                    left.value === "execScript") {
                                    warning("W061", left);

                                    if (p[0] && [0].id === "(string)") {
                                        addInternalSrc(left, p[0].value);
                                    }
                                } else if (p[0] && p[0].id === "(string)" &&
                                    (left.value === "setTimeout" ||
                                        left.value === "setInterval")) {
                                    warning("W066", left);
                                    addInternalSrc(left, p[0].value);
                                } else if (p[0] && p[0].id === "(string)" &&
                                    left.value === "." &&
                                    left.left.value === "window" &&
                                    (left.right === "setTimeout" ||
                                        left.right === "setInterval")) {
                                    warning("W066", left);
                                    addInternalSrc(left, p[0].value);
                                }
                            }
                            if (!left.identifier && left.id !== "." && left.id !== "[" && left.id !== "=>" &&
                                left.id !== "(" && left.id !== "&&" && left.id !== "||" && left.id !== "?" &&
                                !(state.inES6() && left["(name)"])) {
                                warning("W067", that);
                            }
                        }

                        that.left = left;
                        return that;
                    }, 155, true).exps = true;

                    prefix("(", function() {
                        var pn = state.tokens.next,
                            pn1, i = -1;
                        var ret, triggerFnExpr, first, last;
                        var parens = 1;
                        var opening = state.tokens.curr;
                        var preceeding = state.tokens.prev;
                        var isNecessary = !state.option.singleGroups;

                        do {
                            if (pn.value === "(") {
                                parens += 1;
                            } else if (pn.value === ")") {
                                parens -= 1;
                            }

                            i += 1;
                            pn1 = pn;
                            pn = peek(i);
                        } while (!(parens === 0 && pn1.value === ")") && pn.value !== ";" && pn.type !== "(end)");

                        if (state.tokens.next.id === "function") {
                            triggerFnExpr = state.tokens.next.immed = true;
                        }
                        if (pn.value === "=>") {
                            return doFunction({
                                type: "arrow",
                                parsedOpening: true
                            });
                        }

                        var exprs = [];

                        if (state.tokens.next.id !== ")") {
                            for (;;) {
                                exprs.push(expression(10));

                                if (state.tokens.next.id !== ",") {
                                    break;
                                }

                                if (state.option.nocomma) {
                                    warning("W127");
                                }

                                comma();
                            }
                        }

                        advance(")", this);
                        if (state.option.immed && exprs[0] && exprs[0].id === "function") {
                            if (state.tokens.next.id !== "(" &&
                                state.tokens.next.id !== "." && state.tokens.next.id !== "[") {
                                warning("W068", this);
                            }
                        }

                        if (!exprs.length) {
                            return;
                        }
                        if (exprs.length > 1) {
                            ret = Object.create(state.syntax[","]);
                            ret.exprs = exprs;

                            first = exprs[0];
                            last = exprs[exprs.length - 1];

                            if (!isNecessary) {
                                isNecessary = preceeding.assign || preceeding.delim;
                            }
                        } else {
                            ret = first = last = exprs[0];

                            if (!isNecessary) {
                                isNecessary =
                                    (opening.beginsStmt && (ret.id === "{" || triggerFnExpr || isFunctor(ret))) ||
                                    (triggerFnExpr &&
                                        (!isEndOfExpr() || state.tokens.prev.id !== "}")) ||
                                    (isFunctor(ret) && !isEndOfExpr()) ||
                                    (ret.id === "{" && preceeding.id === "=>") ||
                                    (ret.type === "(number)" &&
                                        checkPunctuator(pn, ".") && /^\d+$/.test(ret.value));
                            }
                        }

                        if (ret) {
                            if (!isNecessary && (first.left || first.right || ret.exprs)) {
                                isNecessary =
                                    (!isBeginOfExpr(preceeding) && first.lbp <= preceeding.lbp) ||
                                    (!isEndOfExpr() && last.lbp < state.tokens.next.lbp);
                            }

                            if (!isNecessary) {
                                warning("W126", opening);
                            }

                            ret.paren = true;
                        }

                        return ret;
                    });

                    application("=>");

                    infix("[", function(left, that) {
                        var e = expression(10),
                            s;
                        if (e && e.type === "(string)") {
                            if (!state.option.evil && (e.value === "eval" || e.value === "execScript")) {
                                if (isGlobalEval(left, state)) {
                                    warning("W061");
                                }
                            }

                            countMember(e.value);
                            if (!state.option.sub && reg.identifier.test(e.value)) {
                                s = state.syntax[e.value];
                                if (!s || !isReserved(s)) {
                                    warning("W069", state.tokens.prev, e.value);
                                }
                            }
                        }
                        advance("]", that);

                        if (e && e.value === "hasOwnProperty" && state.tokens.next.value === "=") {
                            warning("W001");
                        }

                        that.left = left;
                        that.right = e;
                        return that;
                    }, 160, true);

                    function comprehensiveArrayExpression() {
                        var res = {};
                        res.exps = true;
                        state.funct["(comparray)"].stack();
                        var reversed = false;
                        if (state.tokens.next.value !== "for") {
                            reversed = true;
                            if (!state.inMoz()) {
                                warning("W116", state.tokens.next, "for", state.tokens.next.value);
                            }
                            state.funct["(comparray)"].setState("use");
                            res.right = expression(10);
                        }

                        advance("for");
                        if (state.tokens.next.value === "each") {
                            advance("each");
                            if (!state.inMoz()) {
                                warning("W118", state.tokens.curr, "for each");
                            }
                        }
                        advance("(");
                        state.funct["(comparray)"].setState("define");
                        res.left = expression(130);
                        if (_.contains(["in", "of"], state.tokens.next.value)) {
                            advance();
                        } else {
                            error("E045", state.tokens.curr);
                        }
                        state.funct["(comparray)"].setState("generate");
                        expression(10);

                        advance(")");
                        if (state.tokens.next.value === "if") {
                            advance("if");
                            advance("(");
                            state.funct["(comparray)"].setState("filter");
                            res.filter = expression(10);
                            advance(")");
                        }

                        if (!reversed) {
                            state.funct["(comparray)"].setState("use");
                            res.right = expression(10);
                        }

                        advance("]");
                        state.funct["(comparray)"].unstack();
                        return res;
                    }

                    prefix("[", function() {
                        var blocktype = lookupBlockType();
                        if (blocktype.isCompArray) {
                            if (!state.option.esnext && !state.inMoz()) {
                                warning("W118", state.tokens.curr, "array comprehension");
                            }
                            return comprehensiveArrayExpression();
                        } else if (blocktype.isDestAssign) {
                            this.destructAssign = destructuringPattern({
                                openingParsed: true,
                                assignment: true
                            });
                            return this;
                        }
                        var b = state.tokens.curr.line !== startLine(state.tokens.next);
                        this.first = [];
                        if (b) {
                            indent += state.option.indent;
                            if (state.tokens.next.from === indent + state.option.indent) {
                                indent += state.option.indent;
                            }
                        }
                        while (state.tokens.next.id !== "(end)") {
                            while (state.tokens.next.id === ",") {
                                if (!state.option.elision) {
                                    if (!state.inES5()) {
                                        warning("W070");
                                    } else {
                                        warning("W128");
                                        do {
                                            advance(",");
                                        } while (state.tokens.next.id === ",");
                                        continue;
                                    }
                                }
                                advance(",");
                            }

                            if (state.tokens.next.id === "]") {
                                break;
                            }

                            this.first.push(expression(10));
                            if (state.tokens.next.id === ",") {
                                comma({
                                    allowTrailing: true
                                });
                                if (state.tokens.next.id === "]" && !state.inES5()) {
                                    warning("W070", state.tokens.curr);
                                    break;
                                }
                            } else {
                                break;
                            }
                        }
                        if (b) {
                            indent -= state.option.indent;
                        }
                        advance("]", this);
                        return this;
                    });


                    function isMethod() {
                        return state.funct["(statement)"] && state.funct["(statement)"].type === "class" ||
                            state.funct["(context)"] && state.funct["(context)"]["(verb)"] === "class";
                    }


                    function isPropertyName(token) {
                        return token.identifier || token.id === "(string)" || token.id === "(number)";
                    }


                    function propertyName(preserveOrToken) {
                        var id;
                        var preserve = true;
                        if (typeof preserveOrToken === "object") {
                            id = preserveOrToken;
                        } else {
                            preserve = preserveOrToken;
                            id = optionalidentifier(false, true, preserve);
                        }

                        if (!id) {
                            if (state.tokens.next.id === "(string)") {
                                id = state.tokens.next.value;
                                if (!preserve) {
                                    advance();
                                }
                            } else if (state.tokens.next.id === "(number)") {
                                id = state.tokens.next.value.toString();
                                if (!preserve) {
                                    advance();
                                }
                            }
                        } else if (typeof id === "object") {
                            if (id.id === "(string)" || id.id === "(identifier)") id = id.value;
                            else if (id.id === "(number)") id = id.value.toString();
                        }

                        if (id === "hasOwnProperty") {
                            warning("W001");
                        }

                        return id;
                    }

                    function functionparams(options) {
                        var next;
                        var paramsIds = [];
                        var ident;
                        var tokens = [];
                        var t;
                        var pastDefault = false;
                        var pastRest = false;
                        var arity = 0;
                        var loneArg = options && options.loneArg;

                        if (loneArg && loneArg.identifier === true) {
                            state.funct["(scope)"].addParam(loneArg.value, loneArg);
                            return {
                                arity: 1,
                                params: [loneArg.value]
                            };
                        }

                        next = state.tokens.next;

                        if (!options || !options.parsedOpening) {
                            advance("(");
                        }

                        if (state.tokens.next.id === ")") {
                            advance(")");
                            return;
                        }

                        function addParam(addParamArgs) {
                            state.funct["(scope)"].addParam.apply(state.funct["(scope)"], addParamArgs);
                        }

                        for (;;) {
                            arity++;
                            var currentParams = [];

                            if (_.contains(["{", "["], state.tokens.next.id)) {
                                tokens = destructuringPattern();
                                for (t in tokens) {
                                    t = tokens[t];
                                    if (t.id) {
                                        paramsIds.push(t.id);
                                        currentParams.push([t.id, t.token]);
                                    }
                                }
                            } else {
                                if (checkPunctuator(state.tokens.next, "...")) pastRest = true;
                                ident = identifier(true);
                                if (ident) {
                                    paramsIds.push(ident);
                                    currentParams.push([ident, state.tokens.curr]);
                                } else {
                                    while (!checkPunctuators(state.tokens.next, [",", ")"])) advance();
                                }
                            }
                            if (pastDefault) {
                                if (state.tokens.next.id !== "=") {
                                    error("W138", state.tokens.current);
                                }
                            }
                            if (state.tokens.next.id === "=") {
                                if (!state.inES6()) {
                                    warning("W119", state.tokens.next, "default parameters", "6");
                                }
                                advance("=");
                                pastDefault = true;
                                expression(10);
                            }
                            currentParams.forEach(addParam);

                            if (state.tokens.next.id === ",") {
                                if (pastRest) {
                                    warning("W131", state.tokens.next);
                                }
                                comma();
                            } else {
                                advance(")", next);
                                return {
                                    arity: arity,
                                    params: paramsIds
                                };
                            }
                        }
                    }

                    function functor(name, token, overwrites) {
                        var funct = {
                            "(name)": name,
                            "(breakage)": 0,
                            "(loopage)": 0,
                            "(tokens)": {},
                            "(properties)": {},

                            "(catch)": false,
                            "(global)": false,

                            "(line)": null,
                            "(character)": null,
                            "(metrics)": null,
                            "(statement)": null,
                            "(context)": null,
                            "(scope)": null,
                            "(comparray)": null,
                            "(generator)": null,
                            "(arrow)": null,
                            "(params)": null
                        };

                        if (token) {
                            _.extend(funct, {
                                "(line)": token.line,
                                "(character)": token.character,
                                "(metrics)": createMetrics(token)
                            });
                        }

                        _.extend(funct, overwrites);

                        if (funct["(context)"]) {
                            funct["(scope)"] = funct["(context)"]["(scope)"];
                            funct["(comparray)"] = funct["(context)"]["(comparray)"];
                        }

                        return funct;
                    }

                    function isFunctor(token) {
                        return "(scope)" in token;
                    }

                    function hasParsedCode(funct) {
                        return funct["(global)"] && !funct["(verb)"];
                    }

                    function doTemplateLiteral(left) {
                        var ctx = this.context;
                        var noSubst = this.noSubst;
                        var depth = this.depth;

                        if (!noSubst) {
                            while (!end()) {
                                if (!state.tokens.next.template || state.tokens.next.depth > depth) {
                                    expression(0); // should probably have different rbp?
                                } else {
                                    advance();
                                }
                            }
                        }

                        return {
                            id: "(template)",
                            type: "(template)",
                            tag: left
                        };

                        function end() {
                            if (state.tokens.curr.template && state.tokens.curr.tail &&
                                state.tokens.curr.context === ctx) return true;
                            var complete = (state.tokens.next.template && state.tokens.next.tail &&
                                state.tokens.next.context === ctx);
                            if (complete) advance();
                            return complete || state.tokens.next.isUnclosed;
                        }
                    }

                    function doFunction(options) {
                        var f, token, name, statement, classExprBinding, isGenerator, isArrow, ignoreLoopFunc;
                        var oldOption = state.option;
                        var oldIgnored = state.ignored;

                        if (options) {
                            name = options.name;
                            statement = options.statement;
                            classExprBinding = options.classExprBinding;
                            isGenerator = options.type === "generator";
                            isArrow = options.type === "arrow";
                            ignoreLoopFunc = options.ignoreLoopFunc;
                        }

                        state.option = Object.create(state.option);
                        state.ignored = Object.create(state.ignored);

                        state.funct = functor(name || state.nameStack.infer(), state.tokens.next, {
                            "(statement)": statement,
                            "(context)": state.funct,
                            "(arrow)": isArrow,
                            "(generator)": isGenerator
                        });

                        f = state.funct;
                        token = state.tokens.curr;
                        token.funct = state.funct;

                        functions.push(state.funct);
                        state.funct["(scope)"].stack("functionouter");
                        var internallyAccessibleName = name || classExprBinding;
                        if (internallyAccessibleName) {
                            state.funct["(scope)"].block.add(internallyAccessibleName,
                                classExprBinding ? "class" : "function", state.tokens.curr, false);
                        }
                        state.funct["(scope)"].stack("functionparams");

                        var paramsInfo = functionparams(options);

                        if (paramsInfo) {
                            state.funct["(params)"] = paramsInfo.params;
                            state.funct["(metrics)"].arity = paramsInfo.arity;
                            state.funct["(metrics)"].verifyMaxParametersPerFunction();
                        } else {
                            state.funct["(metrics)"].arity = 0;
                        }

                        if (isArrow) {
                            if (!state.inES6(true)) {
                                warning("W119", state.tokens.curr, "arrow function syntax (=>)", "6");
                            }

                            if (!options.loneArg) {
                                advance("=>");
                            }
                        }

                        block(false, true, true, isArrow);

                        if (!state.option.noyield && isGenerator &&
                            state.funct["(generator)"] !== "yielded") {
                            warning("W124", state.tokens.curr);
                        }

                        state.funct["(metrics)"].verifyMaxStatementsPerFunction();
                        state.funct["(metrics)"].verifyMaxComplexityPerFunction();
                        state.funct["(unusedOption)"] = state.option.unused;
                        state.option = oldOption;
                        state.ignored = oldIgnored;
                        state.funct["(last)"] = state.tokens.curr.line;
                        state.funct["(lastcharacter)"] = state.tokens.curr.character;
                        state.funct["(scope)"].unstack(); // also does usage and label checks
                        state.funct["(scope)"].unstack();

                        state.funct = state.funct["(context)"];

                        if (!ignoreLoopFunc && !state.option.loopfunc && state.funct["(loopage)"]) {
                            if (f["(isCapturing)"]) {
                                warning("W083", token);
                            }
                        }

                        return f;
                    }

                    function createMetrics(functionStartToken) {
                        return {
                            statementCount: 0,
                            nestedBlockDepth: -1,
                            ComplexityCount: 1,
                            arity: 0,

                            verifyMaxStatementsPerFunction: function() {
                                if (state.option.maxstatements &&
                                    this.statementCount > state.option.maxstatements) {
                                    warning("W071", functionStartToken, this.statementCount);
                                }
                            },

                            verifyMaxParametersPerFunction: function() {
                                if (_.isNumber(state.option.maxparams) &&
                                    this.arity > state.option.maxparams) {
                                    warning("W072", functionStartToken, this.arity);
                                }
                            },

                            verifyMaxNestedBlockDepthPerFunction: function() {
                                if (state.option.maxdepth &&
                                    this.nestedBlockDepth > 0 &&
                                    this.nestedBlockDepth === state.option.maxdepth + 1) {
                                    warning("W073", null, this.nestedBlockDepth);
                                }
                            },

                            verifyMaxComplexityPerFunction: function() {
                                var max = state.option.maxcomplexity;
                                var cc = this.ComplexityCount;
                                if (max && cc > max) {
                                    warning("W074", functionStartToken, cc);
                                }
                            }
                        };
                    }

                    function increaseComplexityCount() {
                        state.funct["(metrics)"].ComplexityCount += 1;
                    }

                    function checkCondAssignment(expr) {
                        var id, paren;
                        if (expr) {
                            id = expr.id;
                            paren = expr.paren;
                            if (id === "," && (expr = expr.exprs[expr.exprs.length - 1])) {
                                id = expr.id;
                                paren = paren || expr.paren;
                            }
                        }
                        switch (id) {
                            case "=":
                            case "+=":
                            case "-=":
                            case "*=":
                            case "%=":
                            case "&=":
                            case "|=":
                            case "^=":
                            case "/=":
                                if (!paren && !state.option.boss) {
                                    warning("W084");
                                }
                        }
                    }

                    function checkProperties(props) {
                        if (state.inES5()) {
                            for (var name in props) {
                                if (props[name] && props[name].setterToken && !props[name].getterToken) {
                                    warning("W078", props[name].setterToken);
                                }
                            }
                        }
                    }

                    function metaProperty(name, c) {
                        if (checkPunctuator(state.tokens.next, ".")) {
                            var left = state.tokens.curr.id;
                            advance(".");
                            var id = identifier();
                            state.tokens.curr.isMetaProperty = true;
                            if (name !== id) {
                                error("E057", state.tokens.prev, left, id);
                            } else {
                                c();
                            }
                            return state.tokens.curr;
                        }
                    }

                    (function(x) {
                        x.nud = function() {
                            var b, f, i, p, t, isGeneratorMethod = false,
                                nextVal;
                            var props = Object.create(null); // All properties, including accessors

                            b = state.tokens.curr.line !== startLine(state.tokens.next);
                            if (b) {
                                indent += state.option.indent;
                                if (state.tokens.next.from === indent + state.option.indent) {
                                    indent += state.option.indent;
                                }
                            }

                            var blocktype = lookupBlockType();
                            if (blocktype.isDestAssign) {
                                this.destructAssign = destructuringPattern({
                                    openingParsed: true,
                                    assignment: true
                                });
                                return this;
                            }

                            for (;;) {
                                if (state.tokens.next.id === "}") {
                                    break;
                                }

                                nextVal = state.tokens.next.value;
                                if (state.tokens.next.identifier &&
                                    (peekIgnoreEOL().id === "," || peekIgnoreEOL().id === "}")) {
                                    if (!state.inES6()) {
                                        warning("W104", state.tokens.next, "object short notation", "6");
                                    }
                                    i = propertyName(true);
                                    saveProperty(props, i, state.tokens.next);

                                    expression(10);

                                } else if (peek().id !== ":" && (nextVal === "get" || nextVal === "set")) {
                                    advance(nextVal);

                                    if (!state.inES5()) {
                                        error("E034");
                                    }

                                    i = propertyName();
                                    if (!i && !state.inES6()) {
                                        error("E035");
                                    }
                                    if (i) {
                                        saveAccessor(nextVal, props, i, state.tokens.curr);
                                    }

                                    t = state.tokens.next;
                                    f = doFunction();
                                    p = f["(params)"];
                                    if (nextVal === "get" && i && p) {
                                        warning("W076", t, p[0], i);
                                    } else if (nextVal === "set" && i && (!p || p.length !== 1)) {
                                        warning("W077", t, i);
                                    }
                                } else {
                                    if (state.tokens.next.value === "*" && state.tokens.next.type === "(punctuator)") {
                                        if (!state.inES6()) {
                                            warning("W104", state.tokens.next, "generator functions", "6");
                                        }
                                        advance("*");
                                        isGeneratorMethod = true;
                                    } else {
                                        isGeneratorMethod = false;
                                    }

                                    if (state.tokens.next.id === "[") {
                                        i = computedPropertyName();
                                        state.nameStack.set(i);
                                    } else {
                                        state.nameStack.set(state.tokens.next);
                                        i = propertyName();
                                        saveProperty(props, i, state.tokens.next);

                                        if (typeof i !== "string") {
                                            break;
                                        }
                                    }

                                    if (state.tokens.next.value === "(") {
                                        if (!state.inES6()) {
                                            warning("W104", state.tokens.curr, "concise methods", "6");
                                        }
                                        doFunction({
                                            type: isGeneratorMethod ? "generator" : null
                                        });
                                    } else {
                                        advance(":");
                                        expression(10);
                                    }
                                }

                                countMember(i);

                                if (state.tokens.next.id === ",") {
                                    comma({
                                        allowTrailing: true,
                                        property: true
                                    });
                                    if (state.tokens.next.id === ",") {
                                        warning("W070", state.tokens.curr);
                                    } else if (state.tokens.next.id === "}" && !state.inES5()) {
                                        warning("W070", state.tokens.curr);
                                    }
                                } else {
                                    break;
                                }
                            }
                            if (b) {
                                indent -= state.option.indent;
                            }
                            advance("}", this);

                            checkProperties(props);

                            return this;
                        };
                        x.fud = function() {
                            error("E036", state.tokens.curr);
                        };
                    }(delim("{")));

                    function destructuringPattern(options) {
                        var isAssignment = options && options.assignment;

                        if (!state.inES6()) {
                            warning("W104", state.tokens.curr,
                                isAssignment ? "destructuring assignment" : "destructuring binding", "6");
                        }

                        return destructuringPatternRecursive(options);
                    }

                    function destructuringPatternRecursive(options) {
                        var ids;
                        var identifiers = [];
                        var openingParsed = options && options.openingParsed;
                        var isAssignment = options && options.assignment;
                        var recursiveOptions = isAssignment ? {
                            assignment: isAssignment
                        } : null;
                        var firstToken = openingParsed ? state.tokens.curr : state.tokens.next;

                        var nextInnerDE = function() {
                            var ident;
                            if (checkPunctuators(state.tokens.next, ["[", "{"])) {
                                ids = destructuringPatternRecursive(recursiveOptions);
                                for (var id in ids) {
                                    id = ids[id];
                                    identifiers.push({
                                        id: id.id,
                                        token: id.token
                                    });
                                }
                            } else if (checkPunctuator(state.tokens.next, ",")) {
                                identifiers.push({
                                    id: null,
                                    token: state.tokens.curr
                                });
                            } else if (checkPunctuator(state.tokens.next, "(")) {
                                advance("(");
                                nextInnerDE();
                                advance(")");
                            } else {
                                var is_rest = checkPunctuator(state.tokens.next, "...");

                                if (isAssignment) {
                                    var identifierToken = is_rest ? peek(0) : state.tokens.next;
                                    if (!identifierToken.identifier) {
                                        warning("E030", identifierToken, identifierToken.value);
                                    }
                                    var assignTarget = expression(155);
                                    if (assignTarget) {
                                        checkLeftSideAssign(assignTarget);
                                        if (assignTarget.identifier) {
                                            ident = assignTarget.value;
                                        }
                                    }
                                } else {
                                    ident = identifier();
                                }
                                if (ident) {
                                    identifiers.push({
                                        id: ident,
                                        token: state.tokens.curr
                                    });
                                }
                                return is_rest;
                            }
                            return false;
                        };
                        var assignmentProperty = function() {
                            var id;
                            if (checkPunctuator(state.tokens.next, "[")) {
                                advance("[");
                                expression(10);
                                advance("]");
                                advance(":");
                                nextInnerDE();
                            } else if (state.tokens.next.id === "(string)" ||
                                state.tokens.next.id === "(number)") {
                                advance();
                                advance(":");
                                nextInnerDE();
                            } else {
                                id = identifier();
                                if (checkPunctuator(state.tokens.next, ":")) {
                                    advance(":");
                                    nextInnerDE();
                                } else if (id) {
                                    if (isAssignment) {
                                        checkLeftSideAssign(state.tokens.curr);
                                    }
                                    identifiers.push({
                                        id: id,
                                        token: state.tokens.curr
                                    });
                                }
                            }
                        };
                        if (checkPunctuator(firstToken, "[")) {
                            if (!openingParsed) {
                                advance("[");
                            }
                            if (checkPunctuator(state.tokens.next, "]")) {
                                warning("W137", state.tokens.curr);
                            }
                            var element_after_rest = false;
                            while (!checkPunctuator(state.tokens.next, "]")) {
                                if (nextInnerDE() && !element_after_rest &&
                                    checkPunctuator(state.tokens.next, ",")) {
                                    warning("W130", state.tokens.next);
                                    element_after_rest = true;
                                }
                                if (checkPunctuator(state.tokens.next, "=")) {
                                    if (checkPunctuator(state.tokens.prev, "...")) {
                                        advance("]");
                                    } else {
                                        advance("=");
                                    }
                                    if (state.tokens.next.id === "undefined") {
                                        warning("W080", state.tokens.prev, state.tokens.prev.value);
                                    }
                                    expression(10);
                                }
                                if (!checkPunctuator(state.tokens.next, "]")) {
                                    advance(",");
                                }
                            }
                            advance("]");
                        } else if (checkPunctuator(firstToken, "{")) {

                            if (!openingParsed) {
                                advance("{");
                            }
                            if (checkPunctuator(state.tokens.next, "}")) {
                                warning("W137", state.tokens.curr);
                            }
                            while (!checkPunctuator(state.tokens.next, "}")) {
                                assignmentProperty();
                                if (checkPunctuator(state.tokens.next, "=")) {
                                    advance("=");
                                    if (state.tokens.next.id === "undefined") {
                                        warning("W080", state.tokens.prev, state.tokens.prev.value);
                                    }
                                    expression(10);
                                }
                                if (!checkPunctuator(state.tokens.next, "}")) {
                                    advance(",");
                                    if (checkPunctuator(state.tokens.next, "}")) {
                                        break;
                                    }
                                }
                            }
                            advance("}");
                        }
                        return identifiers;
                    }

                    function destructuringPatternMatch(tokens, value) {
                        var first = value.first;

                        if (!first)
                            return;

                        _.zip(tokens, Array.isArray(first) ? first : [first]).forEach(function(val) {
                            var token = val[0];
                            var value = val[1];

                            if (token && value)
                                token.first = value;
                            else if (token && token.first && !value)
                                warning("W080", token.first, token.first.value);
                        });
                    }

                    function blockVariableStatement(type, statement, context) {

                        var prefix = context && context.prefix;
                        var inexport = context && context.inexport;
                        var isLet = type === "let";
                        var isConst = type === "const";
                        var tokens, lone, value, letblock;

                        if (!state.inES6()) {
                            warning("W104", state.tokens.curr, type, "6");
                        }

                        if (isLet && state.tokens.next.value === "(") {
                            if (!state.inMoz()) {
                                warning("W118", state.tokens.next, "let block");
                            }
                            advance("(");
                            state.funct["(scope)"].stack();
                            letblock = true;
                        } else if (state.funct["(noblockscopedvar)"]) {
                            error("E048", state.tokens.curr, isConst ? "Const" : "Let");
                        }

                        statement.first = [];
                        for (;;) {
                            var names = [];
                            if (_.contains(["{", "["], state.tokens.next.value)) {
                                tokens = destructuringPattern();
                                lone = false;
                            } else {
                                tokens = [{
                                    id: identifier(),
                                    token: state.tokens.curr
                                }];
                                lone = true;
                            }

                            if (!prefix && isConst && state.tokens.next.id !== "=") {
                                warning("E012", state.tokens.curr, state.tokens.curr.value);
                            }

                            for (var t in tokens) {
                                if (tokens.hasOwnProperty(t)) {
                                    t = tokens[t];
                                    if (state.funct["(scope)"].block.isGlobal()) {
                                        if (predefined[t.id] === false) {
                                            warning("W079", t.token, t.id);
                                        }
                                    }
                                    if (t.id && !state.funct["(noblockscopedvar)"]) {
                                        state.funct["(scope)"].addlabel(t.id, {
                                            type: type,
                                            token: t.token
                                        });
                                        names.push(t.token);

                                        if (lone && inexport) {
                                            state.funct["(scope)"].setExported(t.token.value, t.token);
                                        }
                                    }
                                }
                            }

                            if (state.tokens.next.id === "=") {
                                advance("=");
                                if (!prefix && state.tokens.next.id === "undefined") {
                                    warning("W080", state.tokens.prev, state.tokens.prev.value);
                                }
                                if (!prefix && peek(0).id === "=" && state.tokens.next.identifier) {
                                    warning("W120", state.tokens.next, state.tokens.next.value);
                                }
                                value = expression(prefix ? 120 : 10);
                                if (lone) {
                                    tokens[0].first = value;
                                } else {
                                    destructuringPatternMatch(names, value);
                                }
                            }

                            statement.first = statement.first.concat(names);

                            if (state.tokens.next.id !== ",") {
                                break;
                            }
                            comma();
                        }
                        if (letblock) {
                            advance(")");
                            block(true, true);
                            statement.block = true;
                            state.funct["(scope)"].unstack();
                        }

                        return statement;
                    }

                    var conststatement = stmt("const", function(context) {
                        return blockVariableStatement("const", this, context);
                    });
                    conststatement.exps = true;

                    var letstatement = stmt("let", function(context) {
                        return blockVariableStatement("let", this, context);
                    });
                    letstatement.exps = true;

                    var varstatement = stmt("var", function(context) {
                        var prefix = context && context.prefix;
                        var inexport = context && context.inexport;
                        var tokens, lone, value;
                        var implied = context && context.implied;
                        var report = !(context && context.ignore);

                        this.first = [];
                        for (;;) {
                            var names = [];
                            if (_.contains(["{", "["], state.tokens.next.value)) {
                                tokens = destructuringPattern();
                                lone = false;
                            } else {
                                tokens = [{
                                    id: identifier(),
                                    token: state.tokens.curr
                                }];
                                lone = true;
                            }

                            if (!(prefix && implied) && report && state.option.varstmt) {
                                warning("W132", this);
                            }

                            this.first = this.first.concat(names);

                            for (var t in tokens) {
                                if (tokens.hasOwnProperty(t)) {
                                    t = tokens[t];
                                    if (!implied && state.funct["(global)"]) {
                                        if (predefined[t.id] === false) {
                                            warning("W079", t.token, t.id);
                                        } else if (state.option.futurehostile === false) {
                                            if ((!state.inES5() && vars.ecmaIdentifiers[5][t.id] === false) ||
                                                (!state.inES6() && vars.ecmaIdentifiers[6][t.id] === false)) {
                                                warning("W129", t.token, t.id);
                                            }
                                        }
                                    }
                                    if (t.id) {
                                        if (implied === "for") {

                                            if (!state.funct["(scope)"].has(t.id)) {
                                                if (report) warning("W088", t.token, t.id);
                                            }
                                            state.funct["(scope)"].block.use(t.id, t.token);
                                        } else {
                                            state.funct["(scope)"].addlabel(t.id, {
                                                type: "var",
                                                token: t.token
                                            });

                                            if (lone && inexport) {
                                                state.funct["(scope)"].setExported(t.id, t.token);
                                            }
                                        }
                                        names.push(t.token);
                                    }
                                }
                            }

                            if (state.tokens.next.id === "=") {
                                state.nameStack.set(state.tokens.curr);

                                advance("=");
                                if (!prefix && report && !state.funct["(loopage)"] &&
                                    state.tokens.next.id === "undefined") {
                                    warning("W080", state.tokens.prev, state.tokens.prev.value);
                                }
                                if (peek(0).id === "=" && state.tokens.next.identifier) {
                                    if (!prefix && report &&
                                        !state.funct["(params)"] ||
                                        state.funct["(params)"].indexOf(state.tokens.next.value) === -1) {
                                        warning("W120", state.tokens.next, state.tokens.next.value);
                                    }
                                }
                                value = expression(prefix ? 120 : 10);
                                if (lone) {
                                    tokens[0].first = value;
                                } else {
                                    destructuringPatternMatch(names, value);
                                }
                            }

                            if (state.tokens.next.id !== ",") {
                                break;
                            }
                            comma();
                        }

                        return this;
                    });
                    varstatement.exps = true;

                    blockstmt("class", function() {
                        return classdef.call(this, true);
                    });

                    function classdef(isStatement) {
                        if (!state.inES6()) {
                            warning("W104", state.tokens.curr, "class", "6");
                        }
                        if (isStatement) {
                            this.name = identifier();

                            state.funct["(scope)"].addlabel(this.name, {
                                type: "class",
                                token: state.tokens.curr
                            });
                        } else if (state.tokens.next.identifier && state.tokens.next.value !== "extends") {
                            this.name = identifier();
                            this.namedExpr = true;
                        } else {
                            this.name = state.nameStack.infer();
                        }
                        classtail(this);
                        return this;
                    }

                    function classtail(c) {
                        var wasInClassBody = state.inClassBody;
                        if (state.tokens.next.value === "extends") {
                            advance("extends");
                            c.heritage = expression(10);
                        }

                        state.inClassBody = true;
                        advance("{");
                        c.body = classbody(c);
                        advance("}");
                        state.inClassBody = wasInClassBody;
                    }

                    function classbody(c) {
                        var name;
                        var isStatic;
                        var isGenerator;
                        var getset;
                        var props = Object.create(null);
                        var staticProps = Object.create(null);
                        var computed;
                        for (var i = 0; state.tokens.next.id !== "}"; ++i) {
                            name = state.tokens.next;
                            isStatic = false;
                            isGenerator = false;
                            getset = null;
                            if (name.id === ";") {
                                warning("W032");
                                advance(";");
                                continue;
                            }

                            if (name.id === "*") {
                                isGenerator = true;
                                advance("*");
                                name = state.tokens.next;
                            }
                            if (name.id === "[") {
                                name = computedPropertyName();
                                computed = true;
                            } else if (isPropertyName(name)) {
                                advance();
                                computed = false;
                                if (name.identifier && name.value === "static") {
                                    if (checkPunctuator(state.tokens.next, "*")) {
                                        isGenerator = true;
                                        advance("*");
                                    }
                                    if (isPropertyName(state.tokens.next) || state.tokens.next.id === "[") {
                                        computed = state.tokens.next.id === "[";
                                        isStatic = true;
                                        name = state.tokens.next;
                                        if (state.tokens.next.id === "[") {
                                            name = computedPropertyName();
                                        } else advance();
                                    }
                                }

                                if (name.identifier && (name.value === "get" || name.value === "set")) {
                                    if (isPropertyName(state.tokens.next) || state.tokens.next.id === "[") {
                                        computed = state.tokens.next.id === "[";
                                        getset = name;
                                        name = state.tokens.next;
                                        if (state.tokens.next.id === "[") {
                                            name = computedPropertyName();
                                        } else advance();
                                    }
                                }
                            } else {
                                warning("W052", state.tokens.next, state.tokens.next.value || state.tokens.next.type);
                                advance();
                                continue;
                            }

                            if (!checkPunctuator(state.tokens.next, "(")) {
                                error("E054", state.tokens.next, state.tokens.next.value);
                                while (state.tokens.next.id !== "}" &&
                                    !checkPunctuator(state.tokens.next, "(")) {
                                    advance();
                                }
                                if (state.tokens.next.value !== "(") {
                                    doFunction({
                                        statement: c
                                    });
                                }
                            }

                            if (!computed) {
                                if (getset) {
                                    saveAccessor(
                                        getset.value, isStatic ? staticProps : props, name.value, name, true, isStatic);
                                } else {
                                    if (name.value === "constructor") {
                                        state.nameStack.set(c);
                                    } else {
                                        state.nameStack.set(name);
                                    }
                                    saveProperty(isStatic ? staticProps : props, name.value, name, true, isStatic);
                                }
                            }

                            if (getset && name.value === "constructor") {
                                var propDesc = getset.value === "get" ? "class getter method" : "class setter method";
                                error("E049", name, propDesc, "constructor");
                            } else if (name.value === "prototype") {
                                error("E049", name, "class method", "prototype");
                            }

                            propertyName(name);

                            doFunction({
                                statement: c,
                                type: isGenerator ? "generator" : null,
                                classExprBinding: c.namedExpr ? c.name : null
                            });
                        }

                        checkProperties(props);
                    }

                    blockstmt("function", function(context) {
                        var inexport = context && context.inexport;
                        var generator = false;
                        if (state.tokens.next.value === "*") {
                            advance("*");
                            if (state.inES6({
                                    strict: true
                                })) {
                                generator = true;
                            } else {
                                warning("W119", state.tokens.curr, "function*", "6");
                            }
                        }
                        if (inblock) {
                            warning("W082", state.tokens.curr);
                        }
                        var i = optionalidentifier();

                        state.funct["(scope)"].addlabel(i, {
                            type: "function",
                            token: state.tokens.curr
                        });

                        if (i === undefined) {
                            warning("W025");
                        } else if (inexport) {
                            state.funct["(scope)"].setExported(i, state.tokens.prev);
                        }

                        doFunction({
                            name: i,
                            statement: this,
                            type: generator ? "generator" : null,
                            ignoreLoopFunc: inblock // a declaration may already have warned
                        });
                        if (state.tokens.next.id === "(" && state.tokens.next.line === state.tokens.curr.line) {
                            error("E039");
                        }
                        return this;
                    });

                    prefix("function", function() {
                        var generator = false;

                        if (state.tokens.next.value === "*") {
                            if (!state.inES6()) {
                                warning("W119", state.tokens.curr, "function*", "6");
                            }
                            advance("*");
                            generator = true;
                        }

                        var i = optionalidentifier();
                        doFunction({
                            name: i,
                            type: generator ? "generator" : null
                        });
                        return this;
                    });

                    blockstmt("if", function() {
                        var t = state.tokens.next;
                        increaseComplexityCount();
                        state.condition = true;
                        advance("(");
                        var expr = expression(0);
                        checkCondAssignment(expr);
                        var forinifcheck = null;
                        if (state.option.forin && state.forinifcheckneeded) {
                            state.forinifcheckneeded = false; // We only need to analyze the first if inside the loop
                            forinifcheck = state.forinifchecks[state.forinifchecks.length - 1];
                            if (expr.type === "(punctuator)" && expr.value === "!") {
                                forinifcheck.type = "(negative)";
                            } else {
                                forinifcheck.type = "(positive)";
                            }
                        }

                        advance(")", t);
                        state.condition = false;
                        var s = block(true, true);
                        if (forinifcheck && forinifcheck.type === "(negative)") {
                            if (s && s[0] && s[0].type === "(identifier)" && s[0].value === "continue") {
                                forinifcheck.type = "(negative-with-continue)";
                            }
                        }

                        if (state.tokens.next.id === "else") {
                            advance("else");
                            if (state.tokens.next.id === "if" || state.tokens.next.id === "switch") {
                                statement();
                            } else {
                                block(true, true);
                            }
                        }
                        return this;
                    });

                    blockstmt("try", function() {
                        var b;

                        function doCatch() {
                            advance("catch");
                            advance("(");

                            state.funct["(scope)"].stack("catchparams");

                            if (checkPunctuators(state.tokens.next, ["[", "{"])) {
                                var tokens = destructuringPattern();
                                _.each(tokens, function(token) {
                                    if (token.id) {
                                        state.funct["(scope)"].addParam(token.id, token, "exception");
                                    }
                                });
                            } else if (state.tokens.next.type !== "(identifier)") {
                                warning("E030", state.tokens.next, state.tokens.next.value);
                            } else {
                                state.funct["(scope)"].addParam(identifier(), state.tokens.curr, "exception");
                            }

                            if (state.tokens.next.value === "if") {
                                if (!state.inMoz()) {
                                    warning("W118", state.tokens.curr, "catch filter");
                                }
                                advance("if");
                                expression(0);
                            }

                            advance(")");

                            block(false);

                            state.funct["(scope)"].unstack();
                        }

                        block(true);

                        while (state.tokens.next.id === "catch") {
                            increaseComplexityCount();
                            if (b && (!state.inMoz())) {
                                warning("W118", state.tokens.next, "multiple catch blocks");
                            }
                            doCatch();
                            b = true;
                        }

                        if (state.tokens.next.id === "finally") {
                            advance("finally");
                            block(true);
                            return;
                        }

                        if (!b) {
                            error("E021", state.tokens.next, "catch", state.tokens.next.value);
                        }

                        return this;
                    });

                    blockstmt("while", function() {
                        var t = state.tokens.next;
                        state.funct["(breakage)"] += 1;
                        state.funct["(loopage)"] += 1;
                        increaseComplexityCount();
                        advance("(");
                        checkCondAssignment(expression(0));
                        advance(")", t);
                        block(true, true);
                        state.funct["(breakage)"] -= 1;
                        state.funct["(loopage)"] -= 1;
                        return this;
                    }).labelled = true;

                    blockstmt("with", function() {
                        var t = state.tokens.next;
                        if (state.isStrict()) {
                            error("E010", state.tokens.curr);
                        } else if (!state.option.withstmt) {
                            warning("W085", state.tokens.curr);
                        }

                        advance("(");
                        expression(0);
                        advance(")", t);
                        block(true, true);

                        return this;
                    });

                    blockstmt("switch", function() {
                        var t = state.tokens.next;
                        var g = false;
                        var noindent = false;

                        state.funct["(breakage)"] += 1;
                        advance("(");
                        checkCondAssignment(expression(0));
                        advance(")", t);
                        t = state.tokens.next;
                        advance("{");

                        if (state.tokens.next.from === indent)
                            noindent = true;

                        if (!noindent)
                            indent += state.option.indent;

                        this.cases = [];

                        for (;;) {
                            switch (state.tokens.next.id) {
                                case "case":
                                    switch (state.funct["(verb)"]) {
                                        case "yield":
                                        case "break":
                                        case "case":
                                        case "continue":
                                        case "return":
                                        case "switch":
                                        case "throw":
                                            break;
                                        default:
                                            if (!state.tokens.curr.caseFallsThrough) {
                                                warning("W086", state.tokens.curr, "case");
                                            }
                                    }

                                    advance("case");
                                    this.cases.push(expression(0));
                                    increaseComplexityCount();
                                    g = true;
                                    advance(":");
                                    state.funct["(verb)"] = "case";
                                    break;
                                case "default":
                                    switch (state.funct["(verb)"]) {
                                        case "yield":
                                        case "break":
                                        case "continue":
                                        case "return":
                                        case "throw":
                                            break;
                                        default:
                                            if (this.cases.length) {
                                                if (!state.tokens.curr.caseFallsThrough) {
                                                    warning("W086", state.tokens.curr, "default");
                                                }
                                            }
                                    }

                                    advance("default");
                                    g = true;
                                    advance(":");
                                    break;
                                case "}":
                                    if (!noindent)
                                        indent -= state.option.indent;

                                    advance("}", t);
                                    state.funct["(breakage)"] -= 1;
                                    state.funct["(verb)"] = undefined;
                                    return;
                                case "(end)":
                                    error("E023", state.tokens.next, "}");
                                    return;
                                default:
                                    indent += state.option.indent;
                                    if (g) {
                                        switch (state.tokens.curr.id) {
                                            case ",":
                                                error("E040");
                                                return;
                                            case ":":
                                                g = false;
                                                statements();
                                                break;
                                            default:
                                                error("E025", state.tokens.curr);
                                                return;
                                        }
                                    } else {
                                        if (state.tokens.curr.id === ":") {
                                            advance(":");
                                            error("E024", state.tokens.curr, ":");
                                            statements();
                                        } else {
                                            error("E021", state.tokens.next, "case", state.tokens.next.value);
                                            return;
                                        }
                                    }
                                    indent -= state.option.indent;
                            }
                        }
                        return this;
                    }).labelled = true;

                    stmt("debugger", function() {
                        if (!state.option.debug) {
                            warning("W087", this);
                        }
                        return this;
                    }).exps = true;

                    (function() {
                        var x = stmt("do", function() {
                            state.funct["(breakage)"] += 1;
                            state.funct["(loopage)"] += 1;
                            increaseComplexityCount();

                            this.first = block(true, true);
                            advance("while");
                            var t = state.tokens.next;
                            advance("(");
                            checkCondAssignment(expression(0));
                            advance(")", t);
                            state.funct["(breakage)"] -= 1;
                            state.funct["(loopage)"] -= 1;
                            return this;
                        });
                        x.labelled = true;
                        x.exps = true;
                    }());

                    blockstmt("for", function() {
                        var s, t = state.tokens.next;
                        var letscope = false;
                        var foreachtok = null;

                        if (t.value === "each") {
                            foreachtok = t;
                            advance("each");
                            if (!state.inMoz()) {
                                warning("W118", state.tokens.curr, "for each");
                            }
                        }

                        increaseComplexityCount();
                        advance("(");
                        var nextop; // contains the token of the "in" or "of" operator
                        var i = 0;
                        var inof = ["in", "of"];
                        var level = 0; // BindingPattern "level" --- level 0 === no BindingPattern
                        var comma; // First comma punctuator at level 0
                        var initializer; // First initializer at level 0
                        if (checkPunctuators(state.tokens.next, ["{", "["])) ++level;
                        do {
                            nextop = peek(i);
                            ++i;
                            if (checkPunctuators(nextop, ["{", "["])) ++level;
                            else if (checkPunctuators(nextop, ["}", "]"])) --level;
                            if (level < 0) break;
                            if (level === 0) {
                                if (!comma && checkPunctuator(nextop, ",")) comma = nextop;
                                else if (!initializer && checkPunctuator(nextop, "=")) initializer = nextop;
                            }
                        } while (level > 0 || !_.contains(inof, nextop.value) && nextop.value !== ";" &&
                            nextop.type !== "(end)"); // Is this a JSCS bug? This looks really weird.
                        if (_.contains(inof, nextop.value)) {
                            if (!state.inES6() && nextop.value === "of") {
                                warning("W104", nextop, "for of", "6");
                            }

                            var ok = !(initializer || comma);
                            if (initializer) {
                                error("W133", comma, nextop.value, "initializer is forbidden");
                            }

                            if (comma) {
                                error("W133", comma, nextop.value, "more than one ForBinding");
                            }

                            if (state.tokens.next.id === "var") {
                                advance("var");
                                state.tokens.curr.fud({
                                    prefix: true
                                });
                            } else if (state.tokens.next.id === "let" || state.tokens.next.id === "const") {
                                advance(state.tokens.next.id);
                                letscope = true;
                                state.funct["(scope)"].stack();
                                state.tokens.curr.fud({
                                    prefix: true
                                });
                            } else {
                                Object.create(varstatement).fud({
                                    prefix: true,
                                    implied: "for",
                                    ignore: !ok
                                });
                            }
                            advance(nextop.value);
                            expression(20);
                            advance(")", t);

                            if (nextop.value === "in" && state.option.forin) {
                                state.forinifcheckneeded = true;

                                if (state.forinifchecks === undefined) {
                                    state.forinifchecks = [];
                                }
                                state.forinifchecks.push({
                                    type: "(none)"
                                });
                            }

                            state.funct["(breakage)"] += 1;
                            state.funct["(loopage)"] += 1;

                            s = block(true, true);

                            if (nextop.value === "in" && state.option.forin) {
                                if (state.forinifchecks && state.forinifchecks.length > 0) {
                                    var check = state.forinifchecks.pop();

                                    if ( // No if statement or not the first statement in loop body
                                        s && s.length > 0 && (typeof s[0] !== "object" || s[0].value !== "if") ||
                                        check.type === "(positive)" && s.length > 1 ||
                                        check.type === "(negative)") {
                                        warning("W089", this);
                                    }
                                }
                                state.forinifcheckneeded = false;
                            }

                            state.funct["(breakage)"] -= 1;
                            state.funct["(loopage)"] -= 1;
                        } else {
                            if (foreachtok) {
                                error("E045", foreachtok);
                            }
                            if (state.tokens.next.id !== ";") {
                                if (state.tokens.next.id === "var") {
                                    advance("var");
                                    state.tokens.curr.fud();
                                } else if (state.tokens.next.id === "let") {
                                    advance("let");
                                    letscope = true;
                                    state.funct["(scope)"].stack();
                                    state.tokens.curr.fud();
                                } else {
                                    for (;;) {
                                        expression(0, "for");
                                        if (state.tokens.next.id !== ",") {
                                            break;
                                        }
                                        comma();
                                    }
                                }
                            }
                            nolinebreak(state.tokens.curr);
                            advance(";");
                            state.funct["(loopage)"] += 1;
                            if (state.tokens.next.id !== ";") {
                                checkCondAssignment(expression(0));
                            }
                            nolinebreak(state.tokens.curr);
                            advance(";");
                            if (state.tokens.next.id === ";") {
                                error("E021", state.tokens.next, ")", ";");
                            }
                            if (state.tokens.next.id !== ")") {
                                for (;;) {
                                    expression(0, "for");
                                    if (state.tokens.next.id !== ",") {
                                        break;
                                    }
                                    comma();
                                }
                            }
                            advance(")", t);
                            state.funct["(breakage)"] += 1;
                            block(true, true);
                            state.funct["(breakage)"] -= 1;
                            state.funct["(loopage)"] -= 1;

                        }
                        if (letscope) {
                            state.funct["(scope)"].unstack();
                        }
                        return this;
                    }).labelled = true;


                    stmt("break", function() {
                        var v = state.tokens.next.value;

                        if (!state.option.asi)
                            nolinebreak(this);

                        if (state.tokens.next.id !== ";" && !state.tokens.next.reach &&
                            state.tokens.curr.line === startLine(state.tokens.next)) {
                            if (!state.funct["(scope)"].funct.hasBreakLabel(v)) {
                                warning("W090", state.tokens.next, v);
                            }
                            this.first = state.tokens.next;
                            advance();
                        } else {
                            if (state.funct["(breakage)"] === 0)
                                warning("W052", state.tokens.next, this.value);
                        }

                        reachable(this);

                        return this;
                    }).exps = true;


                    stmt("continue", function() {
                        var v = state.tokens.next.value;

                        if (state.funct["(breakage)"] === 0)
                            warning("W052", state.tokens.next, this.value);
                        if (!state.funct["(loopage)"])
                            warning("W052", state.tokens.next, this.value);

                        if (!state.option.asi)
                            nolinebreak(this);

                        if (state.tokens.next.id !== ";" && !state.tokens.next.reach) {
                            if (state.tokens.curr.line === startLine(state.tokens.next)) {
                                if (!state.funct["(scope)"].funct.hasBreakLabel(v)) {
                                    warning("W090", state.tokens.next, v);
                                }
                                this.first = state.tokens.next;
                                advance();
                            }
                        }

                        reachable(this);

                        return this;
                    }).exps = true;


                    stmt("return", function() {
                        if (this.line === startLine(state.tokens.next)) {
                            if (state.tokens.next.id !== ";" && !state.tokens.next.reach) {
                                this.first = expression(0);

                                if (this.first &&
                                    this.first.type === "(punctuator)" && this.first.value === "=" &&
                                    !this.first.paren && !state.option.boss) {
                                    warningAt("W093", this.first.line, this.first.character);
                                }
                            }
                        } else {
                            if (state.tokens.next.type === "(punctuator)" &&
                                ["[", "{", "+", "-"].indexOf(state.tokens.next.value) > -1) {
                                nolinebreak(this); // always warn (Line breaking error)
                            }
                        }

                        reachable(this);

                        return this;
                    }).exps = true;

                    (function(x) {
                        x.exps = true;
                        x.lbp = 25;
                    }(prefix("yield", function() {
                        var prev = state.tokens.prev;
                        if (state.inES6(true) && !state.funct["(generator)"]) {
                            if (!("(catch)" === state.funct["(name)"] && state.funct["(context)"]["(generator)"])) {
                                error("E046", state.tokens.curr, "yield");
                            }
                        } else if (!state.inES6()) {
                            warning("W104", state.tokens.curr, "yield", "6");
                        }
                        state.funct["(generator)"] = "yielded";
                        var delegatingYield = false;

                        if (state.tokens.next.value === "*") {
                            delegatingYield = true;
                            advance("*");
                        }

                        if (this.line === startLine(state.tokens.next) || !state.inMoz()) {
                            if (delegatingYield ||
                                (state.tokens.next.id !== ";" && !state.option.asi &&
                                    !state.tokens.next.reach && state.tokens.next.nud)) {

                                nobreaknonadjacent(state.tokens.curr, state.tokens.next);
                                this.first = expression(10);

                                if (this.first.type === "(punctuator)" && this.first.value === "=" &&
                                    !this.first.paren && !state.option.boss) {
                                    warningAt("W093", this.first.line, this.first.character);
                                }
                            }

                            if (state.inMoz() && state.tokens.next.id !== ")" &&
                                (prev.lbp > 30 || (!prev.assign && !isEndOfExpr()) || prev.id === "yield")) {
                                error("E050", this);
                            }
                        } else if (!state.option.asi) {
                            nolinebreak(this); // always warn (Line breaking error)
                        }
                        return this;
                    })));


                    stmt("throw", function() {
                        nolinebreak(this);
                        this.first = expression(20);

                        reachable(this);

                        return this;
                    }).exps = true;

                    stmt("import", function() {
                        if (!state.inES6()) {
                            warning("W119", state.tokens.curr, "import", "6");
                        }

                        if (state.tokens.next.type === "(string)") {
                            advance("(string)");
                            return this;
                        }

                        if (state.tokens.next.identifier) {
                            this.name = identifier();
                            state.funct["(scope)"].addlabel(this.name, {
                                type: "const",
                                token: state.tokens.curr
                            });

                            if (state.tokens.next.value === ",") {
                                advance(",");
                            } else {
                                advance("from");
                                advance("(string)");
                                return this;
                            }
                        }

                        if (state.tokens.next.id === "*") {
                            advance("*");
                            advance("as");
                            if (state.tokens.next.identifier) {
                                this.name = identifier();
                                state.funct["(scope)"].addlabel(this.name, {
                                    type: "const",
                                    token: state.tokens.curr
                                });
                            }
                        } else {
                            advance("{");
                            for (;;) {
                                if (state.tokens.next.value === "}") {
                                    advance("}");
                                    break;
                                }
                                var importName;
                                if (state.tokens.next.type === "default") {
                                    importName = "default";
                                    advance("default");
                                } else {
                                    importName = identifier();
                                }
                                if (state.tokens.next.value === "as") {
                                    advance("as");
                                    importName = identifier();
                                }
                                state.funct["(scope)"].addlabel(importName, {
                                    type: "const",
                                    token: state.tokens.curr
                                });

                                if (state.tokens.next.value === ",") {
                                    advance(",");
                                } else if (state.tokens.next.value === "}") {
                                    advance("}");
                                    break;
                                } else {
                                    error("E024", state.tokens.next, state.tokens.next.value);
                                    break;
                                }
                            }
                        }
                        advance("from");
                        advance("(string)");
                        return this;
                    }).exps = true;

                    stmt("export", function() {
                        var ok = true;
                        var token;
                        var identifier;

                        if (!state.inES6()) {
                            warning("W119", state.tokens.curr, "export", "6");
                            ok = false;
                        }

                        if (!state.funct["(scope)"].block.isGlobal()) {
                            error("E053", state.tokens.curr);
                            ok = false;
                        }

                        if (state.tokens.next.value === "*") {
                            advance("*");
                            advance("from");
                            advance("(string)");
                            return this;
                        }

                        if (state.tokens.next.type === "default") {
                            state.nameStack.set(state.tokens.next);
                            advance("default");
                            var exportType = state.tokens.next.id;
                            if (exportType === "function" || exportType === "class") {
                                this.block = true;
                            }

                            token = peek();

                            expression(10);

                            identifier = token.value;

                            if (this.block) {
                                state.funct["(scope)"].addlabel(identifier, {
                                    type: exportType,
                                    token: token
                                });

                                state.funct["(scope)"].setExported(identifier, token);
                            }

                            return this;
                        }

                        if (state.tokens.next.value === "{") {
                            advance("{");
                            var exportedTokens = [];
                            for (;;) {
                                if (!state.tokens.next.identifier) {
                                    error("E030", state.tokens.next, state.tokens.next.value);
                                }
                                advance();

                                exportedTokens.push(state.tokens.curr);

                                if (state.tokens.next.value === "as") {
                                    advance("as");
                                    if (!state.tokens.next.identifier) {
                                        error("E030", state.tokens.next, state.tokens.next.value);
                                    }
                                    advance();
                                }

                                if (state.tokens.next.value === ",") {
                                    advance(",");
                                } else if (state.tokens.next.value === "}") {
                                    advance("}");
                                    break;
                                } else {
                                    error("E024", state.tokens.next, state.tokens.next.value);
                                    break;
                                }
                            }
                            if (state.tokens.next.value === "from") {
                                advance("from");
                                advance("(string)");
                            } else if (ok) {
                                exportedTokens.forEach(function(token) {
                                    state.funct["(scope)"].setExported(token.value, token);
                                });
                            }
                            return this;
                        }

                        if (state.tokens.next.id === "var") {
                            advance("var");
                            state.tokens.curr.fud({
                                inexport: true
                            });
                        } else if (state.tokens.next.id === "let") {
                            advance("let");
                            state.tokens.curr.fud({
                                inexport: true
                            });
                        } else if (state.tokens.next.id === "const") {
                            advance("const");
                            state.tokens.curr.fud({
                                inexport: true
                            });
                        } else if (state.tokens.next.id === "function") {
                            this.block = true;
                            advance("function");
                            state.syntax["function"].fud({
                                inexport: true
                            });
                        } else if (state.tokens.next.id === "class") {
                            this.block = true;
                            advance("class");
                            var classNameToken = state.tokens.next;
                            state.syntax["class"].fud();
                            state.funct["(scope)"].setExported(classNameToken.value, classNameToken);
                        } else {
                            error("E024", state.tokens.next, state.tokens.next.value);
                        }

                        return this;
                    }).exps = true;

                    FutureReservedWord("abstract");
                    FutureReservedWord("boolean");
                    FutureReservedWord("byte");
                    FutureReservedWord("char");
                    FutureReservedWord("class", {
                        es5: true,
                        nud: classdef
                    });
                    FutureReservedWord("double");
                    FutureReservedWord("enum", {
                        es5: true
                    });
                    FutureReservedWord("export", {
                        es5: true
                    });
                    FutureReservedWord("extends", {
                        es5: true
                    });
                    FutureReservedWord("final");
                    FutureReservedWord("float");
                    FutureReservedWord("goto");
                    FutureReservedWord("implements", {
                        es5: true,
                        strictOnly: true
                    });
                    FutureReservedWord("import", {
                        es5: true
                    });
                    FutureReservedWord("int");
                    FutureReservedWord("interface", {
                        es5: true,
                        strictOnly: true
                    });
                    FutureReservedWord("long");
                    FutureReservedWord("native");
                    FutureReservedWord("package", {
                        es5: true,
                        strictOnly: true
                    });
                    FutureReservedWord("private", {
                        es5: true,
                        strictOnly: true
                    });
                    FutureReservedWord("protected", {
                        es5: true,
                        strictOnly: true
                    });
                    FutureReservedWord("public", {
                        es5: true,
                        strictOnly: true
                    });
                    FutureReservedWord("short");
                    FutureReservedWord("static", {
                        es5: true,
                        strictOnly: true
                    });
                    FutureReservedWord("super", {
                        es5: true
                    });
                    FutureReservedWord("synchronized");
                    FutureReservedWord("transient");
                    FutureReservedWord("volatile");

                    var lookupBlockType = function() {
                        var pn, pn1, prev;
                        var i = -1;
                        var bracketStack = 0;
                        var ret = {};
                        if (checkPunctuators(state.tokens.curr, ["[", "{"])) {
                            bracketStack += 1;
                        }
                        do {
                            prev = i === -1 ? state.tokens.curr : pn;
                            pn = i === -1 ? state.tokens.next : peek(i);
                            pn1 = peek(i + 1);
                            i = i + 1;
                            if (checkPunctuators(pn, ["[", "{"])) {
                                bracketStack += 1;
                            } else if (checkPunctuators(pn, ["]", "}"])) {
                                bracketStack -= 1;
                            }
                            if (bracketStack === 1 && pn.identifier && pn.value === "for" &&
                                !checkPunctuator(prev, ".")) {
                                ret.isCompArray = true;
                                ret.notJson = true;
                                break;
                            }
                            if (bracketStack === 0 && checkPunctuators(pn, ["}", "]"])) {
                                if (pn1.value === "=") {
                                    ret.isDestAssign = true;
                                    ret.notJson = true;
                                    break;
                                } else if (pn1.value === ".") {
                                    ret.notJson = true;
                                    break;
                                }
                            }
                            if (checkPunctuator(pn, ";")) {
                                ret.isBlock = true;
                                ret.notJson = true;
                            }
                        } while (bracketStack > 0 && pn.id !== "(end)");
                        return ret;
                    };

                    function saveProperty(props, name, tkn, isClass, isStatic) {
                        var msg = ["key", "class method", "static class method"];
                        msg = msg[(isClass || false) + (isStatic || false)];
                        if (tkn.identifier) {
                            name = tkn.value;
                        }

                        if (props[name] && name !== "__proto__") {
                            warning("W075", state.tokens.next, msg, name);
                        } else {
                            props[name] = Object.create(null);
                        }

                        props[name].basic = true;
                        props[name].basictkn = tkn;
                    }

                    function saveAccessor(accessorType, props, name, tkn, isClass, isStatic) {
                        var flagName = accessorType === "get" ? "getterToken" : "setterToken";
                        var msg = "";

                        if (isClass) {
                            if (isStatic) {
                                msg += "static ";
                            }
                            msg += accessorType + "ter method";
                        } else {
                            msg = "key";
                        }

                        state.tokens.curr.accessorType = accessorType;
                        state.nameStack.set(tkn);

                        if (props[name]) {
                            if ((props[name].basic || props[name][flagName]) && name !== "__proto__") {
                                warning("W075", state.tokens.next, msg, name);
                            }
                        } else {
                            props[name] = Object.create(null);
                        }

                        props[name][flagName] = tkn;
                    }

                    function computedPropertyName() {
                        advance("[");
                        if (!state.inES6()) {
                            warning("W119", state.tokens.curr, "computed property names", "6");
                        }
                        var value = expression(10);
                        advance("]");
                        return value;
                    }

                    function checkPunctuators(token, values) {
                        if (token.type === "(punctuator)") {
                            return _.contains(values, token.value);
                        }
                        return false;
                    }

                    function checkPunctuator(token, value) {
                        return token.type === "(punctuator)" && token.value === value;
                    }

                    function destructuringAssignOrJsonValue() {

                        var block = lookupBlockType();
                        if (block.notJson) {
                            if (!state.inES6() && block.isDestAssign) {
                                warning("W104", state.tokens.curr, "destructuring assignment", "6");
                            }
                            statements();
                        } else {
                            state.option.laxbreak = true;
                            state.jsonMode = true;
                            jsonValue();
                        }
                    }

                    var arrayComprehension = function() {
                        var CompArray = function() {
                            this.mode = "use";
                            this.variables = [];
                        };
                        var _carrays = [];
                        var _current;

                        function declare(v) {
                            var l = _current.variables.filter(function(elt) {
                                if (elt.value === v) {
                                    elt.undef = false;
                                    return v;
                                }
                            }).length;
                            return l !== 0;
                        }

                        function use(v) {
                            var l = _current.variables.filter(function(elt) {
                                if (elt.value === v && !elt.undef) {
                                    if (elt.unused === true) {
                                        elt.unused = false;
                                    }
                                    return v;
                                }
                            }).length;
                            return (l === 0);
                        }
                        return {
                            stack: function() {
                                _current = new CompArray();
                                _carrays.push(_current);
                            },
                            unstack: function() {
                                _current.variables.filter(function(v) {
                                    if (v.unused)
                                        warning("W098", v.token, v.raw_text || v.value);
                                    if (v.undef)
                                        state.funct["(scope)"].block.use(v.value, v.token);
                                });
                                _carrays.splice(-1, 1);
                                _current = _carrays[_carrays.length - 1];
                            },
                            setState: function(s) {
                                if (_.contains(["use", "define", "generate", "filter"], s))
                                    _current.mode = s;
                            },
                            check: function(v) {
                                if (!_current) {
                                    return;
                                }
                                if (_current && _current.mode === "use") {
                                    if (use(v)) {
                                        _current.variables.push({
                                            funct: state.funct,
                                            token: state.tokens.curr,
                                            value: v,
                                            undef: true,
                                            unused: false
                                        });
                                    }
                                    return true;
                                } else if (_current && _current.mode === "define") {
                                    if (!declare(v)) {
                                        _current.variables.push({
                                            funct: state.funct,
                                            token: state.tokens.curr,
                                            value: v,
                                            undef: false,
                                            unused: true
                                        });
                                    }
                                    return true;
                                } else if (_current && _current.mode === "generate") {
                                    state.funct["(scope)"].block.use(v, state.tokens.curr);
                                    return true;
                                } else if (_current && _current.mode === "filter") {
                                    if (use(v)) {
                                        state.funct["(scope)"].block.use(v, state.tokens.curr);
                                    }
                                    return true;
                                }
                                return false;
                            }
                        };
                    };

                    function jsonValue() {
                        function jsonObject() {
                            var o = {},
                                t = state.tokens.next;
                            advance("{");
                            if (state.tokens.next.id !== "}") {
                                for (;;) {
                                    if (state.tokens.next.id === "(end)") {
                                        error("E026", state.tokens.next, t.line);
                                    } else if (state.tokens.next.id === "}") {
                                        warning("W094", state.tokens.curr);
                                        break;
                                    } else if (state.tokens.next.id === ",") {
                                        error("E028", state.tokens.next);
                                    } else if (state.tokens.next.id !== "(string)") {
                                        warning("W095", state.tokens.next, state.tokens.next.value);
                                    }
                                    if (o[state.tokens.next.value] === true) {
                                        warning("W075", state.tokens.next, "key", state.tokens.next.value);
                                    } else if ((state.tokens.next.value === "__proto__" &&
                                            !state.option.proto) || (state.tokens.next.value === "__iterator__" &&
                                            !state.option.iterator)) {
                                        warning("W096", state.tokens.next, state.tokens.next.value);
                                    } else {
                                        o[state.tokens.next.value] = true;
                                    }
                                    advance();
                                    advance(":");
                                    jsonValue();
                                    if (state.tokens.next.id !== ",") {
                                        break;
                                    }
                                    advance(",");
                                }
                            }
                            advance("}");
                        }

                        function jsonArray() {
                            var t = state.tokens.next;
                            advance("[");
                            if (state.tokens.next.id !== "]") {
                                for (;;) {
                                    if (state.tokens.next.id === "(end)") {
                                        error("E027", state.tokens.next, t.line);
                                    } else if (state.tokens.next.id === "]") {
                                        warning("W094", state.tokens.curr);
                                        break;
                                    } else if (state.tokens.next.id === ",") {
                                        error("E028", state.tokens.next);
                                    }
                                    jsonValue();
                                    if (state.tokens.next.id !== ",") {
                                        break;
                                    }
                                    advance(",");
                                }
                            }
                            advance("]");
                        }

                        switch (state.tokens.next.id) {
                            case "{":
                                jsonObject();
                                break;
                            case "[":
                                jsonArray();
                                break;
                            case "true":
                            case "false":
                            case "null":
                            case "(number)":
                            case "(string)":
                                advance();
                                break;
                            case "-":
                                advance("-");
                                advance("(number)");
                                break;
                            default:
                                error("E003", state.tokens.next);
                        }
                    }

                    var escapeRegex = function(str) {
                        return str.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&");
                    };
                    var itself = function(s, o, g) {
                        var i, k, x, reIgnoreStr, reIgnore;
                        var optionKeys;
                        var newOptionObj = {};
                        var newIgnoredObj = {};

                        o = _.clone(o);
                        state.reset();

                        if (o && o.scope) {
                            JSHINT.scope = o.scope;
                        } else {
                            JSHINT.errors = [];
                            JSHINT.undefs = [];
                            JSHINT.internals = [];
                            JSHINT.blacklist = {};
                            JSHINT.scope = "(main)";
                        }

                        predefined = Object.create(null);
                        combine(predefined, vars.ecmaIdentifiers[3]);
                        combine(predefined, vars.reservedVars);

                        combine(predefined, g || {});

                        declared = Object.create(null);
                        var exported = Object.create(null); // Variables that live outside the current file

                        function each(obj, cb) {
                            if (!obj)
                                return;

                            if (!Array.isArray(obj) && typeof obj === "object")
                                obj = Object.keys(obj);

                            obj.forEach(cb);
                        }

                        if (o) {
                            each(o.predef || null, function(item) {
                                var slice, prop;

                                if (item[0] === "-") {
                                    slice = item.slice(1);
                                    JSHINT.blacklist[slice] = slice;
                                    delete predefined[slice];
                                } else {
                                    prop = Object.getOwnPropertyDescriptor(o.predef, item);
                                    predefined[item] = prop ? prop.value : false;
                                }
                            });

                            each(o.exported || null, function(item) {
                                exported[item] = true;
                            });

                            delete o.predef;
                            delete o.exported;

                            optionKeys = Object.keys(o);
                            for (x = 0; x < optionKeys.length; x++) {
                                if (/^-W\d{3}$/g.test(optionKeys[x])) {
                                    newIgnoredObj[optionKeys[x].slice(1)] = true;
                                } else {
                                    var optionKey = optionKeys[x];
                                    newOptionObj[optionKey] = o[optionKey];
                                    if ((optionKey === "esversion" && o[optionKey] === 5) ||
                                        (optionKey === "es5" && o[optionKey])) {
                                        warning("I003");
                                    }

                                    if (optionKeys[x] === "newcap" && o[optionKey] === false)
                                        newOptionObj["(explicitNewcap)"] = true;
                                }
                            }
                        }

                        state.option = newOptionObj;
                        state.ignored = newIgnoredObj;

                        state.option.indent = state.option.indent || 4;
                        state.option.maxerr = state.option.maxerr || 50;

                        indent = 1;

                        var scopeManagerInst = scopeManager(state, predefined, exported, declared);
                        scopeManagerInst.on("warning", function(ev) {
                            warning.apply(null, [ev.code, ev.token].concat(ev.data));
                        });

                        scopeManagerInst.on("error", function(ev) {
                            error.apply(null, [ev.code, ev.token].concat(ev.data));
                        });

                        state.funct = functor("(global)", null, {
                            "(global)": true,
                            "(scope)": scopeManagerInst,
                            "(comparray)": arrayComprehension(),
                            "(metrics)": createMetrics(state.tokens.next)
                        });

                        functions = [state.funct];
                        urls = [];
                        stack = null;
                        member = {};
                        membersOnly = null;
                        inblock = false;
                        lookahead = [];

                        if (!isString(s) && !Array.isArray(s)) {
                            errorAt("E004", 0);
                            return false;
                        }

                        api = {
                            get isJSON() {
                                return state.jsonMode;
                            },

                            getOption: function(name) {
                                return state.option[name] || null;
                            },

                            getCache: function(name) {
                                return state.cache[name];
                            },

                            setCache: function(name, value) {
                                state.cache[name] = value;
                            },

                            warn: function(code, data) {
                                warningAt.apply(null, [code, data.line, data.char].concat(data.data));
                            },

                            on: function(names, listener) {
                                names.split(" ").forEach(function(name) {
                                    emitter.on(name, listener);
                                }.bind(this));
                            }
                        };

                        emitter.removeAllListeners();
                        (extraModules || []).forEach(function(func) {
                            func(api);
                        });

                        state.tokens.prev = state.tokens.curr = state.tokens.next = state.syntax["(begin)"];

                        if (o && o.ignoreDelimiters) {

                            if (!Array.isArray(o.ignoreDelimiters)) {
                                o.ignoreDelimiters = [o.ignoreDelimiters];
                            }

                            o.ignoreDelimiters.forEach(function(delimiterPair) {
                                if (!delimiterPair.start || !delimiterPair.end)
                                    return;

                                reIgnoreStr = escapeRegex(delimiterPair.start) +
                                    "[\\s\\S]*?" +
                                    escapeRegex(delimiterPair.end);

                                reIgnore = new RegExp(reIgnoreStr, "ig");

                                s = s.replace(reIgnore, function(match) {
                                    return match.replace(/./g, " ");
                                });
                            });
                        }

                        lex = new Lexer(s);

                        lex.on("warning", function(ev) {
                            warningAt.apply(null, [ev.code, ev.line, ev.character].concat(ev.data));
                        });

                        lex.on("error", function(ev) {
                            errorAt.apply(null, [ev.code, ev.line, ev.character].concat(ev.data));
                        });

                        lex.on("fatal", function(ev) {
                            quit("E041", ev.line, ev.from);
                        });

                        lex.on("Identifier", function(ev) {
                            emitter.emit("Identifier", ev);
                        });

                        lex.on("String", function(ev) {
                            emitter.emit("String", ev);
                        });

                        lex.on("Number", function(ev) {
                            emitter.emit("Number", ev);
                        });

                        lex.start();
                        for (var name in o) {
                            if (_.has(o, name)) {
                                checkOption(name, state.tokens.curr);
                            }
                        }

                        assume();
                        combine(predefined, g || {});
                        comma.first = true;

                        try {
                            advance();
                            switch (state.tokens.next.id) {
                                case "{":
                                case "[":
                                    destructuringAssignOrJsonValue();
                                    break;
                                default:
                                    directives();

                                    if (state.directive["use strict"]) {
                                        if (state.option.strict !== "global") {
                                            warning("W097", state.tokens.prev);
                                        }
                                    }

                                    statements();
                            }

                            if (state.tokens.next.id !== "(end)") {
                                quit("E041", state.tokens.curr.line);
                            }

                            state.funct["(scope)"].unstack();

                        } catch (err) {
                            if (err && err.name === "JSHintError") {
                                var nt = state.tokens.next || {};
                                JSHINT.errors.push({
                                    scope: "(main)",
                                    raw: err.raw,
                                    code: err.code,
                                    reason: err.message,
                                    line: err.line || nt.line,
                                    character: err.character || nt.from
                                }, null);
                            } else {
                                throw err;
                            }
                        }

                        if (JSHINT.scope === "(main)") {
                            o = o || {};

                            for (i = 0; i < JSHINT.internals.length; i += 1) {
                                k = JSHINT.internals[i];
                                o.scope = k.elem;
                                itself(k.value, o, g);
                            }
                        }

                        return JSHINT.errors.length === 0;
                    };
                    itself.addModule = function(func) {
                        extraModules.push(func);
                    };

                    itself.addModule(style.register);
                    itself.data = function() {
                        var data = {
                            functions: [],
                            options: state.option
                        };

                        var fu, f, i, j, n, globals;

                        if (itself.errors.length) {
                            data.errors = itself.errors;
                        }

                        if (state.jsonMode) {
                            data.json = true;
                        }

                        var impliedGlobals = state.funct["(scope)"].getImpliedGlobals();
                        if (impliedGlobals.length > 0) {
                            data.implieds = impliedGlobals;
                        }

                        if (urls.length > 0) {
                            data.urls = urls;
                        }

                        globals = state.funct["(scope)"].getUsedOrDefinedGlobals();
                        if (globals.length > 0) {
                            data.globals = globals;
                        }

                        for (i = 1; i < functions.length; i += 1) {
                            f = functions[i];
                            fu = {};

                            for (j = 0; j < functionicity.length; j += 1) {
                                fu[functionicity[j]] = [];
                            }

                            for (j = 0; j < functionicity.length; j += 1) {
                                if (fu[functionicity[j]].length === 0) {
                                    delete fu[functionicity[j]];
                                }
                            }

                            fu.name = f["(name)"];
                            fu.param = f["(params)"];
                            fu.line = f["(line)"];
                            fu.character = f["(character)"];
                            fu.last = f["(last)"];
                            fu.lastcharacter = f["(lastcharacter)"];

                            fu.metrics = {
                                complexity: f["(metrics)"].ComplexityCount,
                                parameters: f["(metrics)"].arity,
                                statements: f["(metrics)"].statementCount
                            };

                            data.functions.push(fu);
                        }

                        var unuseds = state.funct["(scope)"].getUnuseds();
                        if (unuseds.length > 0) {
                            data.unused = unuseds;
                        }

                        for (n in member) {
                            if (typeof member[n] === "number") {
                                data.member = member;
                                break;
                            }
                        }

                        return data;
                    };

                    itself.jshint = itself;

                    return itself;
                }());
                if (typeof exports === "object" && exports) {
                    exports.JSHINT = JSHINT;
                }

            }, {
                "../lodash": "/node_modules/jshint/lodash.js",
                "./lex.js": "/node_modules/jshint/src/lex.js",
                "./messages.js": "/node_modules/jshint/src/messages.js",
                "./options.js": "/node_modules/jshint/src/options.js",
                "./reg.js": "/node_modules/jshint/src/reg.js",
                "./scope-manager.js": "/node_modules/jshint/src/scope-manager.js",
                "./state.js": "/node_modules/jshint/src/state.js",
                "./style.js": "/node_modules/jshint/src/style.js",
                "./vars.js": "/node_modules/jshint/src/vars.js",
                "events": "/node_modules/browserify/node_modules/events/events.js"
            }],
            "/node_modules/jshint/src/lex.js": [function(_dereq_, module, exports) {

                "use strict";

                var _ = _dereq_("../lodash");
                var events = _dereq_("events");
                var reg = _dereq_("./reg.js");
                var state = _dereq_("./state.js").state;

                var unicodeData = _dereq_("../data/ascii-identifier-data.js");
                var asciiIdentifierStartTable = unicodeData.asciiIdentifierStartTable;
                var asciiIdentifierPartTable = unicodeData.asciiIdentifierPartTable;

                var Token = {
                    Identifier: 1,
                    Punctuator: 2,
                    NumericLiteral: 3,
                    StringLiteral: 4,
                    Comment: 5,
                    Keyword: 6,
                    NullLiteral: 7,
                    BooleanLiteral: 8,
                    RegExp: 9,
                    TemplateHead: 10,
                    TemplateMiddle: 11,
                    TemplateTail: 12,
                    NoSubstTemplate: 13
                };

                var Context = {
                    Block: 1,
                    Template: 2
                };

                function asyncTrigger() {
                    var _checks = [];

                    return {
                        push: function(fn) {
                            _checks.push(fn);
                        },

                        check: function() {
                            for (var check = 0; check < _checks.length; ++check) {
                                _checks[check]();
                            }

                            _checks.splice(0, _checks.length);
                        }
                    };
                }

                function Lexer(source) {
                    var lines = source;

                    if (typeof lines === "string") {
                        lines = lines
                            .replace(/\r\n/g, "\n")
                            .replace(/\r/g, "\n")
                            .split("\n");
                    }

                    if (lines[0] && lines[0].substr(0, 2) === "#!") {
                        if (lines[0].indexOf("node") !== -1) {
                            state.option.node = true;
                        }
                        lines[0] = "";
                    }

                    this.emitter = new events.EventEmitter();
                    this.source = source;
                    this.setLines(lines);
                    this.prereg = true;

                    this.line = 0;
                    this.char = 1;
                    this.from = 1;
                    this.input = "";
                    this.inComment = false;
                    this.context = [];
                    this.templateStarts = [];

                    for (var i = 0; i < state.option.indent; i += 1) {
                        state.tab += " ";
                    }
                    this.ignoreLinterErrors = false;
                }

                Lexer.prototype = {
                    _lines: [],

                    inContext: function(ctxType) {
                        return this.context.length > 0 && this.context[this.context.length - 1].type === ctxType;
                    },

                    pushContext: function(ctxType) {
                        this.context.push({
                            type: ctxType
                        });
                    },

                    popContext: function() {
                        return this.context.pop();
                    },

                    isContext: function(context) {
                        return this.context.length > 0 && this.context[this.context.length - 1] === context;
                    },

                    currentContext: function() {
                        return this.context.length > 0 && this.context[this.context.length - 1];
                    },

                    getLines: function() {
                        this._lines = state.lines;
                        return this._lines;
                    },

                    setLines: function(val) {
                        this._lines = val;
                        state.lines = this._lines;
                    },
                    peek: function(i) {
                        return this.input.charAt(i || 0);
                    },
                    skip: function(i) {
                        i = i || 1;
                        this.char += i;
                        this.input = this.input.slice(i);
                    },
                    on: function(names, listener) {
                        names.split(" ").forEach(function(name) {
                            this.emitter.on(name, listener);
                        }.bind(this));
                    },
                    trigger: function() {
                        this.emitter.emit.apply(this.emitter, Array.prototype.slice.call(arguments));
                    },
                    triggerAsync: function(type, args, checks, fn) {
                        checks.push(function() {
                            if (fn()) {
                                this.trigger(type, args);
                            }
                        }.bind(this));
                    },
                    scanPunctuator: function() {
                        var ch1 = this.peek();
                        var ch2, ch3, ch4;

                        switch (ch1) {
                            case ".":
                                if ((/^[0-9]$/).test(this.peek(1))) {
                                    return null;
                                }
                                if (this.peek(1) === "." && this.peek(2) === ".") {
                                    return {
                                        type: Token.Punctuator,
                                        value: "..."
                                    };
                                }
                            case "(":
                            case ")":
                            case ";":
                            case ",":
                            case "[":
                            case "]":
                            case ":":
                            case "~":
                            case "?":
                                return {
                                    type: Token.Punctuator,
                                    value: ch1
                                };
                            case "{":
                                this.pushContext(Context.Block);
                                return {
                                    type: Token.Punctuator,
                                    value: ch1
                                };
                            case "}":
                                if (this.inContext(Context.Block)) {
                                    this.popContext();
                                }
                                return {
                                    type: Token.Punctuator,
                                    value: ch1
                                };
                            case "#":
                                return {
                                    type: Token.Punctuator,
                                    value: ch1
                                };
                            case "":
                                return null;
                        }

                        ch2 = this.peek(1);
                        ch3 = this.peek(2);
                        ch4 = this.peek(3);

                        if (ch1 === ">" && ch2 === ">" && ch3 === ">" && ch4 === "=") {
                            return {
                                type: Token.Punctuator,
                                value: ">>>="
                            };
                        }

                        if (ch1 === "=" && ch2 === "=" && ch3 === "=") {
                            return {
                                type: Token.Punctuator,
                                value: "==="
                            };
                        }

                        if (ch1 === "!" && ch2 === "=" && ch3 === "=") {
                            return {
                                type: Token.Punctuator,
                                value: "!=="
                            };
                        }

                        if (ch1 === ">" && ch2 === ">" && ch3 === ">") {
                            return {
                                type: Token.Punctuator,
                                value: ">>>"
                            };
                        }

                        if (ch1 === "<" && ch2 === "<" && ch3 === "=") {
                            return {
                                type: Token.Punctuator,
                                value: "<<="
                            };
                        }

                        if (ch1 === ">" && ch2 === ">" && ch3 === "=") {
                            return {
                                type: Token.Punctuator,
                                value: ">>="
                            };
                        }
                        if (ch1 === "=" && ch2 === ">") {
                            return {
                                type: Token.Punctuator,
                                value: ch1 + ch2
                            };
                        }
                        if (ch1 === ch2 && ("+-<>&|".indexOf(ch1) >= 0)) {
                            return {
                                type: Token.Punctuator,
                                value: ch1 + ch2
                            };
                        }

                        if ("<>=!+-*%&|^".indexOf(ch1) >= 0) {
                            if (ch2 === "=") {
                                return {
                                    type: Token.Punctuator,
                                    value: ch1 + ch2
                                };
                            }

                            return {
                                type: Token.Punctuator,
                                value: ch1
                            };
                        }

                        if (ch1 === "/") {
                            if (ch2 === "=") {
                                return {
                                    type: Token.Punctuator,
                                    value: "/="
                                };
                            }

                            return {
                                type: Token.Punctuator,
                                value: "/"
                            };
                        }

                        return null;
                    },
                    scanComments: function() {
                        var ch1 = this.peek();
                        var ch2 = this.peek(1);
                        var rest = this.input.substr(2);
                        var startLine = this.line;
                        var startChar = this.char;
                        var self = this;

                        function commentToken(label, body, opt) {
                            var special = ["jshint", "jslint", "members", "member", "globals", "global", "exported"];
                            var isSpecial = false;
                            var value = label + body;
                            var commentType = "plain";
                            opt = opt || {};

                            if (opt.isMultiline) {
                                value += "*/";
                            }

                            body = body.replace(/\n/g, " ");

                            if (label === "/*" && reg.fallsThrough.test(body)) {
                                isSpecial = true;
                                commentType = "falls through";
                            }

                            special.forEach(function(str) {
                                if (isSpecial) {
                                    return;
                                }
                                if (label === "//" && str !== "jshint") {
                                    return;
                                }

                                if (body.charAt(str.length) === " " && body.substr(0, str.length) === str) {
                                    isSpecial = true;
                                    label = label + str;
                                    body = body.substr(str.length);
                                }

                                if (!isSpecial && body.charAt(0) === " " && body.charAt(str.length + 1) === " " &&
                                    body.substr(1, str.length) === str) {
                                    isSpecial = true;
                                    label = label + " " + str;
                                    body = body.substr(str.length + 1);
                                }

                                if (!isSpecial) {
                                    return;
                                }

                                switch (str) {
                                    case "member":
                                        commentType = "members";
                                        break;
                                    case "global":
                                        commentType = "globals";
                                        break;
                                    default:
                                        var options = body.split(":").map(function(v) {
                                            return v.replace(/^\s+/, "").replace(/\s+$/, "");
                                        });

                                        if (options.length === 2) {
                                            switch (options[0]) {
                                                case "ignore":
                                                    switch (options[1]) {
                                                        case "start":
                                                            self.ignoringLinterErrors = true;
                                                            isSpecial = false;
                                                            break;
                                                        case "end":
                                                            self.ignoringLinterErrors = false;
                                                            isSpecial = false;
                                                            break;
                                                    }
                                            }
                                        }

                                        commentType = str;
                                }
                            });

                            return {
                                type: Token.Comment,
                                commentType: commentType,
                                value: value,
                                body: body,
                                isSpecial: isSpecial,
                                isMultiline: opt.isMultiline || false,
                                isMalformed: opt.isMalformed || false
                            };
                        }
                        if (ch1 === "*" && ch2 === "/") {
                            this.trigger("error", {
                                code: "E018",
                                line: startLine,
                                character: startChar
                            });

                            this.skip(2);
                            return null;
                        }
                        if (ch1 !== "/" || (ch2 !== "*" && ch2 !== "/")) {
                            return null;
                        }
                        if (ch2 === "/") {
                            this.skip(this.input.length); // Skip to the EOL.
                            return commentToken("//", rest);
                        }

                        var body = "";
                        if (ch2 === "*") {
                            this.inComment = true;
                            this.skip(2);

                            while (this.peek() !== "*" || this.peek(1) !== "/") {
                                if (this.peek() === "") { // End of Line
                                    body += "\n";
                                    if (!this.nextLine()) {
                                        this.trigger("error", {
                                            code: "E017",
                                            line: startLine,
                                            character: startChar
                                        });

                                        this.inComment = false;
                                        return commentToken("/*", body, {
                                            isMultiline: true,
                                            isMalformed: true
                                        });
                                    }
                                } else {
                                    body += this.peek();
                                    this.skip();
                                }
                            }

                            this.skip(2);
                            this.inComment = false;
                            return commentToken("/*", body, {
                                isMultiline: true
                            });
                        }
                    },
                    scanKeyword: function() {
                        var result = /^[a-zA-Z_$][a-zA-Z0-9_$]*/.exec(this.input);
                        var keywords = [
                            "if", "in", "do", "var", "for", "new",
                            "try", "let", "this", "else", "case",
                            "void", "with", "enum", "while", "break",
                            "catch", "throw", "const", "yield", "class",
                            "super", "return", "typeof", "delete",
                            "switch", "export", "import", "default",
                            "finally", "extends", "function", "continue",
                            "debugger", "instanceof"
                        ];

                        if (result && keywords.indexOf(result[0]) >= 0) {
                            return {
                                type: Token.Keyword,
                                value: result[0]
                            };
                        }

                        return null;
                    },
                    scanIdentifier: function() {
                        var id = "";
                        var index = 0;
                        var type, char;

                        function isNonAsciiIdentifierStart(code) {
                            return code > 256;
                        }

                        function isNonAsciiIdentifierPart(code) {
                            return code > 256;
                        }

                        function isHexDigit(str) {
                            return (/^[0-9a-fA-F]$/).test(str);
                        }

                        var readUnicodeEscapeSequence = function() {
                            index += 1;

                            if (this.peek(index) !== "u") {
                                return null;
                            }

                            var ch1 = this.peek(index + 1);
                            var ch2 = this.peek(index + 2);
                            var ch3 = this.peek(index + 3);
                            var ch4 = this.peek(index + 4);
                            var code;

                            if (isHexDigit(ch1) && isHexDigit(ch2) && isHexDigit(ch3) && isHexDigit(ch4)) {
                                code = parseInt(ch1 + ch2 + ch3 + ch4, 16);

                                if (asciiIdentifierPartTable[code] || isNonAsciiIdentifierPart(code)) {
                                    index += 5;
                                    return "\\u" + ch1 + ch2 + ch3 + ch4;
                                }

                                return null;
                            }

                            return null;
                        }.bind(this);

                        var getIdentifierStart = function() {
                            var chr = this.peek(index);
                            var code = chr.charCodeAt(0);

                            if (code === 92) {
                                return readUnicodeEscapeSequence();
                            }

                            if (code < 128) {
                                if (asciiIdentifierStartTable[code]) {
                                    index += 1;
                                    return chr;
                                }

                                return null;
                            }

                            if (isNonAsciiIdentifierStart(code)) {
                                index += 1;
                                return chr;
                            }

                            return null;
                        }.bind(this);

                        var getIdentifierPart = function() {
                            var chr = this.peek(index);
                            var code = chr.charCodeAt(0);

                            if (code === 92) {
                                return readUnicodeEscapeSequence();
                            }

                            if (code < 128) {
                                if (asciiIdentifierPartTable[code]) {
                                    index += 1;
                                    return chr;
                                }

                                return null;
                            }

                            if (isNonAsciiIdentifierPart(code)) {
                                index += 1;
                                return chr;
                            }

                            return null;
                        }.bind(this);

                        function removeEscapeSequences(id) {
                            return id.replace(/\\u([0-9a-fA-F]{4})/g, function(m0, codepoint) {
                                return String.fromCharCode(parseInt(codepoint, 16));
                            });
                        }

                        char = getIdentifierStart();
                        if (char === null) {
                            return null;
                        }

                        id = char;
                        for (;;) {
                            char = getIdentifierPart();

                            if (char === null) {
                                break;
                            }

                            id += char;
                        }

                        switch (id) {
                            case "true":
                            case "false":
                                type = Token.BooleanLiteral;
                                break;
                            case "null":
                                type = Token.NullLiteral;
                                break;
                            default:
                                type = Token.Identifier;
                        }

                        return {
                            type: type,
                            value: removeEscapeSequences(id),
                            text: id,
                            tokenLength: id.length
                        };
                    },
                    scanNumericLiteral: function() {
                        var index = 0;
                        var value = "";
                        var length = this.input.length;
                        var char = this.peek(index);
                        var bad;
                        var isAllowedDigit = isDecimalDigit;
                        var base = 10;
                        var isLegacy = false;

                        function isDecimalDigit(str) {
                            return (/^[0-9]$/).test(str);
                        }

                        function isOctalDigit(str) {
                            return (/^[0-7]$/).test(str);
                        }

                        function isBinaryDigit(str) {
                            return (/^[01]$/).test(str);
                        }

                        function isHexDigit(str) {
                            return (/^[0-9a-fA-F]$/).test(str);
                        }

                        function isIdentifierStart(ch) {
                            return (ch === "$") || (ch === "_") || (ch === "\\") ||
                                (ch >= "a" && ch <= "z") || (ch >= "A" && ch <= "Z");
                        }

                        if (char !== "." && !isDecimalDigit(char)) {
                            return null;
                        }

                        if (char !== ".") {
                            value = this.peek(index);
                            index += 1;
                            char = this.peek(index);

                            if (value === "0") {
                                if (char === "x" || char === "X") {
                                    isAllowedDigit = isHexDigit;
                                    base = 16;

                                    index += 1;
                                    value += char;
                                }
                                if (char === "o" || char === "O") {
                                    isAllowedDigit = isOctalDigit;
                                    base = 8;

                                    if (!state.inES6(true)) {
                                        this.trigger("warning", {
                                            code: "W119",
                                            line: this.line,
                                            character: this.char,
                                            data: ["Octal integer literal", "6"]
                                        });
                                    }

                                    index += 1;
                                    value += char;
                                }
                                if (char === "b" || char === "B") {
                                    isAllowedDigit = isBinaryDigit;
                                    base = 2;

                                    if (!state.inES6(true)) {
                                        this.trigger("warning", {
                                            code: "W119",
                                            line: this.line,
                                            character: this.char,
                                            data: ["Binary integer literal", "6"]
                                        });
                                    }

                                    index += 1;
                                    value += char;
                                }
                                if (isOctalDigit(char)) {
                                    isAllowedDigit = isOctalDigit;
                                    base = 8;
                                    isLegacy = true;
                                    bad = false;

                                    index += 1;
                                    value += char;
                                }

                                if (!isOctalDigit(char) && isDecimalDigit(char)) {
                                    index += 1;
                                    value += char;
                                }
                            }

                            while (index < length) {
                                char = this.peek(index);

                                if (isLegacy && isDecimalDigit(char)) {
                                    bad = true;
                                } else if (!isAllowedDigit(char)) {
                                    break;
                                }
                                value += char;
                                index += 1;
                            }

                            if (isAllowedDigit !== isDecimalDigit) {
                                if (!isLegacy && value.length <= 2) { // 0x
                                    return {
                                        type: Token.NumericLiteral,
                                        value: value,
                                        isMalformed: true
                                    };
                                }

                                if (index < length) {
                                    char = this.peek(index);
                                    if (isIdentifierStart(char)) {
                                        return null;
                                    }
                                }

                                return {
                                    type: Token.NumericLiteral,
                                    value: value,
                                    base: base,
                                    isLegacy: isLegacy,
                                    isMalformed: false
                                };
                            }
                        }

                        if (char === ".") {
                            value += char;
                            index += 1;

                            while (index < length) {
                                char = this.peek(index);
                                if (!isDecimalDigit(char)) {
                                    break;
                                }
                                value += char;
                                index += 1;
                            }
                        }

                        if (char === "e" || char === "E") {
                            value += char;
                            index += 1;
                            char = this.peek(index);

                            if (char === "+" || char === "-") {
                                value += this.peek(index);
                                index += 1;
                            }

                            char = this.peek(index);
                            if (isDecimalDigit(char)) {
                                value += char;
                                index += 1;

                                while (index < length) {
                                    char = this.peek(index);
                                    if (!isDecimalDigit(char)) {
                                        break;
                                    }
                                    value += char;
                                    index += 1;
                                }
                            } else {
                                return null;
                            }
                        }

                        if (index < length) {
                            char = this.peek(index);
                            if (isIdentifierStart(char)) {
                                return null;
                            }
                        }

                        return {
                            type: Token.NumericLiteral,
                            value: value,
                            base: base,
                            isMalformed: !isFinite(value)
                        };
                    },
                    scanEscapeSequence: function(checks) {
                        var allowNewLine = false;
                        var jump = 1;
                        this.skip();
                        var char = this.peek();

                        switch (char) {
                            case "'":
                                this.triggerAsync("warning", {
                                    code: "W114",
                                    line: this.line,
                                    character: this.char,
                                    data: ["\\'"]
                                }, checks, function() {
                                    return state.jsonMode;
                                });
                                break;
                            case "b":
                                char = "\\b";
                                break;
                            case "f":
                                char = "\\f";
                                break;
                            case "n":
                                char = "\\n";
                                break;
                            case "r":
                                char = "\\r";
                                break;
                            case "t":
                                char = "\\t";
                                break;
                            case "0":
                                char = "\\0";
                                var n = parseInt(this.peek(1), 10);
                                this.triggerAsync("warning", {
                                        code: "W115",
                                        line: this.line,
                                        character: this.char
                                    }, checks,
                                    function() {
                                        return n >= 0 && n <= 7 && state.isStrict();
                                    });
                                break;
                            case "u":
                                var hexCode = this.input.substr(1, 4);
                                var code = parseInt(hexCode, 16);
                                if (isNaN(code)) {
                                    this.trigger("warning", {
                                        code: "W052",
                                        line: this.line,
                                        character: this.char,
                                        data: ["u" + hexCode]
                                    });
                                }
                                char = String.fromCharCode(code);
                                jump = 5;
                                break;
                            case "v":
                                this.triggerAsync("warning", {
                                    code: "W114",
                                    line: this.line,
                                    character: this.char,
                                    data: ["\\v"]
                                }, checks, function() {
                                    return state.jsonMode;
                                });

                                char = "\v";
                                break;
                            case "x":
                                var x = parseInt(this.input.substr(1, 2), 16);

                                this.triggerAsync("warning", {
                                    code: "W114",
                                    line: this.line,
                                    character: this.char,
                                    data: ["\\x-"]
                                }, checks, function() {
                                    return state.jsonMode;
                                });

                                char = String.fromCharCode(x);
                                jump = 3;
                                break;
                            case "\\":
                                char = "\\\\";
                                break;
                            case "\"":
                                char = "\\\"";
                                break;
                            case "/":
                                break;
                            case "":
                                allowNewLine = true;
                                char = "";
                                break;
                        }

                        return {
                            char: char,
                            jump: jump,
                            allowNewLine: allowNewLine
                        };
                    },
                    scanTemplateLiteral: function(checks) {
                        var tokenType;
                        var value = "";
                        var ch;
                        var startLine = this.line;
                        var startChar = this.char;
                        var depth = this.templateStarts.length;

                        if (!state.inES6(true)) {
                            return null;
                        } else if (this.peek() === "`") {
                            tokenType = Token.TemplateHead;
                            this.templateStarts.push({
                                line: this.line,
                                char: this.char
                            });
                            depth = this.templateStarts.length;
                            this.skip(1);
                            this.pushContext(Context.Template);
                        } else if (this.inContext(Context.Template) && this.peek() === "}") {
                            tokenType = Token.TemplateMiddle;
                        } else {
                            return null;
                        }

                        while (this.peek() !== "`") {
                            while ((ch = this.peek()) === "") {
                                value += "\n";
                                if (!this.nextLine()) {
                                    var startPos = this.templateStarts.pop();
                                    this.trigger("error", {
                                        code: "E052",
                                        line: startPos.line,
                                        character: startPos.char
                                    });
                                    return {
                                        type: tokenType,
                                        value: value,
                                        startLine: startLine,
                                        startChar: startChar,
                                        isUnclosed: true,
                                        depth: depth,
                                        context: this.popContext()
                                    };
                                }
                            }

                            if (ch === '$' && this.peek(1) === '{') {
                                value += '${';
                                this.skip(2);
                                return {
                                    type: tokenType,
                                    value: value,
                                    startLine: startLine,
                                    startChar: startChar,
                                    isUnclosed: false,
                                    depth: depth,
                                    context: this.currentContext()
                                };
                            } else if (ch === '\\') {
                                var escape = this.scanEscapeSequence(checks);
                                value += escape.char;
                                this.skip(escape.jump);
                            } else if (ch !== '`') {
                                value += ch;
                                this.skip(1);
                            }
                        }
                        tokenType = tokenType === Token.TemplateHead ? Token.NoSubstTemplate : Token.TemplateTail;
                        this.skip(1);
                        this.templateStarts.pop();

                        return {
                            type: tokenType,
                            value: value,
                            startLine: startLine,
                            startChar: startChar,
                            isUnclosed: false,
                            depth: depth,
                            context: this.popContext()
                        };
                    },
                    scanStringLiteral: function(checks) {
                        var quote = this.peek();
                        if (quote !== "\"" && quote !== "'") {
                            return null;
                        }
                        this.triggerAsync("warning", {
                            code: "W108",
                            line: this.line,
                            character: this.char // +1?
                        }, checks, function() {
                            return state.jsonMode && quote !== "\"";
                        });

                        var value = "";
                        var startLine = this.line;
                        var startChar = this.char;
                        var allowNewLine = false;

                        this.skip();

                        while (this.peek() !== quote) {
                            if (this.peek() === "") { // End Of Line

                                if (!allowNewLine) {
                                    this.trigger("warning", {
                                        code: "W112",
                                        line: this.line,
                                        character: this.char
                                    });
                                } else {
                                    allowNewLine = false;

                                    this.triggerAsync("warning", {
                                        code: "W043",
                                        line: this.line,
                                        character: this.char
                                    }, checks, function() {
                                        return !state.option.multistr;
                                    });

                                    this.triggerAsync("warning", {
                                        code: "W042",
                                        line: this.line,
                                        character: this.char
                                    }, checks, function() {
                                        return state.jsonMode && state.option.multistr;
                                    });
                                }

                                if (!this.nextLine()) {
                                    this.trigger("error", {
                                        code: "E029",
                                        line: startLine,
                                        character: startChar
                                    });

                                    return {
                                        type: Token.StringLiteral,
                                        value: value,
                                        startLine: startLine,
                                        startChar: startChar,
                                        isUnclosed: true,
                                        quote: quote
                                    };
                                }

                            } else { // Any character other than End Of Line

                                allowNewLine = false;
                                var char = this.peek();
                                var jump = 1; // A length of a jump, after we're done

                                if (char < " ") {
                                    this.trigger("warning", {
                                        code: "W113",
                                        line: this.line,
                                        character: this.char,
                                        data: ["<non-printable>"]
                                    });
                                }
                                if (char === "\\") {
                                    var parsed = this.scanEscapeSequence(checks);
                                    char = parsed.char;
                                    jump = parsed.jump;
                                    allowNewLine = parsed.allowNewLine;
                                }

                                value += char;
                                this.skip(jump);
                            }
                        }

                        this.skip();
                        return {
                            type: Token.StringLiteral,
                            value: value,
                            startLine: startLine,
                            startChar: startChar,
                            isUnclosed: false,
                            quote: quote
                        };
                    },
                    scanRegExp: function() {
                        var index = 0;
                        var length = this.input.length;
                        var char = this.peek();
                        var value = char;
                        var body = "";
                        var flags = [];
                        var malformed = false;
                        var isCharSet = false;
                        var terminated;

                        var scanUnexpectedChars = function() {
                            if (char < " ") {
                                malformed = true;
                                this.trigger("warning", {
                                    code: "W048",
                                    line: this.line,
                                    character: this.char
                                });
                            }
                            if (char === "<") {
                                malformed = true;
                                this.trigger("warning", {
                                    code: "W049",
                                    line: this.line,
                                    character: this.char,
                                    data: [char]
                                });
                            }
                        }.bind(this);
                        if (!this.prereg || char !== "/") {
                            return null;
                        }

                        index += 1;
                        terminated = false;

                        while (index < length) {
                            char = this.peek(index);
                            value += char;
                            body += char;

                            if (isCharSet) {
                                if (char === "]") {
                                    if (this.peek(index - 1) !== "\\" || this.peek(index - 2) === "\\") {
                                        isCharSet = false;
                                    }
                                }

                                if (char === "\\") {
                                    index += 1;
                                    char = this.peek(index);
                                    body += char;
                                    value += char;

                                    scanUnexpectedChars();
                                }

                                index += 1;
                                continue;
                            }

                            if (char === "\\") {
                                index += 1;
                                char = this.peek(index);
                                body += char;
                                value += char;

                                scanUnexpectedChars();

                                if (char === "/") {
                                    index += 1;
                                    continue;
                                }

                                if (char === "[") {
                                    index += 1;
                                    continue;
                                }
                            }

                            if (char === "[") {
                                isCharSet = true;
                                index += 1;
                                continue;
                            }

                            if (char === "/") {
                                body = body.substr(0, body.length - 1);
                                terminated = true;
                                index += 1;
                                break;
                            }

                            index += 1;
                        }

                        if (!terminated) {
                            this.trigger("error", {
                                code: "E015",
                                line: this.line,
                                character: this.from
                            });

                            return void this.trigger("fatal", {
                                line: this.line,
                                from: this.from
                            });
                        }

                        while (index < length) {
                            char = this.peek(index);
                            if (!/[gim]/.test(char)) {
                                break;
                            }
                            flags.push(char);
                            value += char;
                            index += 1;
                        }

                        try {
                            new RegExp(body, flags.join(""));
                        } catch (err) {
                            malformed = true;
                            this.trigger("error", {
                                code: "E016",
                                line: this.line,
                                character: this.char,
                                data: [err.message] // Platform dependent!
                            });
                        }

                        return {
                            type: Token.RegExp,
                            value: value,
                            flags: flags,
                            isMalformed: malformed
                        };
                    },
                    scanNonBreakingSpaces: function() {
                        return state.option.nonbsp ?
                            this.input.search(/(\u00A0)/) : -1;
                    },
                    scanUnsafeChars: function() {
                        return this.input.search(reg.unsafeChars);
                    },
                    next: function(checks) {
                        this.from = this.char;
                        var start;
                        if (/\s/.test(this.peek())) {
                            start = this.char;

                            while (/\s/.test(this.peek())) {
                                this.from += 1;
                                this.skip();
                            }
                        }

                        var match = this.scanComments() ||
                            this.scanStringLiteral(checks) ||
                            this.scanTemplateLiteral(checks);

                        if (match) {
                            return match;
                        }

                        match =
                            this.scanRegExp() ||
                            this.scanPunctuator() ||
                            this.scanKeyword() ||
                            this.scanIdentifier() ||
                            this.scanNumericLiteral();

                        if (match) {
                            this.skip(match.tokenLength || match.value.length);
                            return match;
                        }

                        return null;
                    },
                    nextLine: function() {
                        var char;

                        if (this.line >= this.getLines().length) {
                            return false;
                        }

                        this.input = this.getLines()[this.line];
                        this.line += 1;
                        this.char = 1;
                        this.from = 1;

                        var inputTrimmed = this.input.trim();

                        var startsWith = function() {
                            return _.some(arguments, function(prefix) {
                                return inputTrimmed.indexOf(prefix) === 0;
                            });
                        };

                        var endsWith = function() {
                            return _.some(arguments, function(suffix) {
                                return inputTrimmed.indexOf(suffix, inputTrimmed.length - suffix.length) !== -1;
                            });
                        };
                        if (this.ignoringLinterErrors === true) {
                            if (!startsWith("/*", "//") && !(this.inComment && endsWith("*/"))) {
                                this.input = "";
                            }
                        }

                        char = this.scanNonBreakingSpaces();
                        if (char >= 0) {
                            this.trigger("warning", {
                                code: "W125",
                                line: this.line,
                                character: char + 1
                            });
                        }

                        this.input = this.input.replace(/\t/g, state.tab);
                        char = this.scanUnsafeChars();

                        if (char >= 0) {
                            this.trigger("warning", {
                                code: "W100",
                                line: this.line,
                                character: char
                            });
                        }

                        if (!this.ignoringLinterErrors && state.option.maxlen &&
                            state.option.maxlen < this.input.length) {
                            var inComment = this.inComment ||
                                startsWith.call(inputTrimmed, "//") ||
                                startsWith.call(inputTrimmed, "/*");

                            var shouldTriggerError = !inComment || !reg.maxlenException.test(inputTrimmed);

                            if (shouldTriggerError) {
                                this.trigger("warning", {
                                    code: "W101",
                                    line: this.line,
                                    character: this.input.length
                                });
                            }
                        }

                        return true;
                    },
                    start: function() {
                        this.nextLine();
                    },
                    token: function() {
                        var checks = asyncTrigger();
                        var token;


                        function isReserved(token, isProperty) {
                            if (!token.reserved) {
                                return false;
                            }
                            var meta = token.meta;

                            if (meta && meta.isFutureReservedWord && state.inES5()) {
                                if (!meta.es5) {
                                    return false;
                                }
                                if (meta.strictOnly) {
                                    if (!state.option.strict && !state.isStrict()) {
                                        return false;
                                    }
                                }

                                if (isProperty) {
                                    return false;
                                }
                            }

                            return true;
                        }
                        var create = function(type, value, isProperty, token) {
                            var obj;

                            if (type !== "(endline)" && type !== "(end)") {
                                this.prereg = false;
                            }

                            if (type === "(punctuator)") {
                                switch (value) {
                                    case ".":
                                    case ")":
                                    case "~":
                                    case "#":
                                    case "]":
                                    case "++":
                                    case "--":
                                        this.prereg = false;
                                        break;
                                    default:
                                        this.prereg = true;
                                }

                                obj = Object.create(state.syntax[value] || state.syntax["(error)"]);
                            }

                            if (type === "(identifier)") {
                                if (value === "return" || value === "case" || value === "typeof") {
                                    this.prereg = true;
                                }

                                if (_.has(state.syntax, value)) {
                                    obj = Object.create(state.syntax[value] || state.syntax["(error)"]);
                                    if (!isReserved(obj, isProperty && type === "(identifier)")) {
                                        obj = null;
                                    }
                                }
                            }

                            if (!obj) {
                                obj = Object.create(state.syntax[type]);
                            }

                            obj.identifier = (type === "(identifier)");
                            obj.type = obj.type || type;
                            obj.value = value;
                            obj.line = this.line;
                            obj.character = this.char;
                            obj.from = this.from;
                            if (obj.identifier && token) obj.raw_text = token.text || token.value;
                            if (token && token.startLine && token.startLine !== this.line) {
                                obj.startLine = token.startLine;
                            }
                            if (token && token.context) {
                                obj.context = token.context;
                            }
                            if (token && token.depth) {
                                obj.depth = token.depth;
                            }
                            if (token && token.isUnclosed) {
                                obj.isUnclosed = token.isUnclosed;
                            }

                            if (isProperty && obj.identifier) {
                                obj.isProperty = isProperty;
                            }

                            obj.check = checks.check;

                            return obj;
                        }.bind(this);

                        for (;;) {
                            if (!this.input.length) {
                                if (this.nextLine()) {
                                    return create("(endline)", "");
                                }

                                if (this.exhausted) {
                                    return null;
                                }

                                this.exhausted = true;
                                return create("(end)", "");
                            }

                            token = this.next(checks);

                            if (!token) {
                                if (this.input.length) {
                                    this.trigger("error", {
                                        code: "E024",
                                        line: this.line,
                                        character: this.char,
                                        data: [this.peek()]
                                    });

                                    this.input = "";
                                }

                                continue;
                            }

                            switch (token.type) {
                                case Token.StringLiteral:
                                    this.triggerAsync("String", {
                                        line: this.line,
                                        char: this.char,
                                        from: this.from,
                                        startLine: token.startLine,
                                        startChar: token.startChar,
                                        value: token.value,
                                        quote: token.quote
                                    }, checks, function() {
                                        return true;
                                    });

                                    return create("(string)", token.value, null, token);

                                case Token.TemplateHead:
                                    this.trigger("TemplateHead", {
                                        line: this.line,
                                        char: this.char,
                                        from: this.from,
                                        startLine: token.startLine,
                                        startChar: token.startChar,
                                        value: token.value
                                    });
                                    return create("(template)", token.value, null, token);

                                case Token.TemplateMiddle:
                                    this.trigger("TemplateMiddle", {
                                        line: this.line,
                                        char: this.char,
                                        from: this.from,
                                        startLine: token.startLine,
                                        startChar: token.startChar,
                                        value: token.value
                                    });
                                    return create("(template middle)", token.value, null, token);

                                case Token.TemplateTail:
                                    this.trigger("TemplateTail", {
                                        line: this.line,
                                        char: this.char,
                                        from: this.from,
                                        startLine: token.startLine,
                                        startChar: token.startChar,
                                        value: token.value
                                    });
                                    return create("(template tail)", token.value, null, token);

                                case Token.NoSubstTemplate:
                                    this.trigger("NoSubstTemplate", {
                                        line: this.line,
                                        char: this.char,
                                        from: this.from,
                                        startLine: token.startLine,
                                        startChar: token.startChar,
                                        value: token.value
                                    });
                                    return create("(no subst template)", token.value, null, token);

                                case Token.Identifier:
                                    this.triggerAsync("Identifier", {
                                        line: this.line,
                                        char: this.char,
                                        from: this.form,
                                        name: token.value,
                                        raw_name: token.text,
                                        isProperty: state.tokens.curr.id === "."
                                    }, checks, function() {
                                        return true;
                                    });
                                case Token.Keyword:
                                case Token.NullLiteral:
                                case Token.BooleanLiteral:
                                    return create("(identifier)", token.value, state.tokens.curr.id === ".", token);

                                case Token.NumericLiteral:
                                    if (token.isMalformed) {
                                        this.trigger("warning", {
                                            code: "W045",
                                            line: this.line,
                                            character: this.char,
                                            data: [token.value]
                                        });
                                    }

                                    this.triggerAsync("warning", {
                                        code: "W114",
                                        line: this.line,
                                        character: this.char,
                                        data: ["0x-"]
                                    }, checks, function() {
                                        return token.base === 16 && state.jsonMode;
                                    });

                                    this.triggerAsync("warning", {
                                        code: "W115",
                                        line: this.line,
                                        character: this.char
                                    }, checks, function() {
                                        return state.isStrict() && token.base === 8 && token.isLegacy;
                                    });

                                    this.trigger("Number", {
                                        line: this.line,
                                        char: this.char,
                                        from: this.from,
                                        value: token.value,
                                        base: token.base,
                                        isMalformed: token.malformed
                                    });

                                    return create("(number)", token.value);

                                case Token.RegExp:
                                    return create("(regexp)", token.value);

                                case Token.Comment:
                                    state.tokens.curr.comment = true;

                                    if (token.isSpecial) {
                                        return {
                                            id: '(comment)',
                                            value: token.value,
                                            body: token.body,
                                            type: token.commentType,
                                            isSpecial: token.isSpecial,
                                            line: this.line,
                                            character: this.char,
                                            from: this.from
                                        };
                                    }

                                    break;

                                case "":
                                    break;

                                default:
                                    return create("(punctuator)", token.value);
                            }
                        }
                    }
                };

                exports.Lexer = Lexer;
                exports.Context = Context;

            }, {
                "../data/ascii-identifier-data.js": "/node_modules/jshint/data/ascii-identifier-data.js",
                "../lodash": "/node_modules/jshint/lodash.js",
                "./reg.js": "/node_modules/jshint/src/reg.js",
                "./state.js": "/node_modules/jshint/src/state.js",
                "events": "/node_modules/browserify/node_modules/events/events.js"
            }],
            "/node_modules/jshint/src/messages.js": [function(_dereq_, module, exports) {
                "use strict";

                var _ = _dereq_("../lodash");

                var errors = {
                    E001: "Bad option: '{a}'.",
                    E002: "Bad option value.",
                    E003: "Expected a JSON value.",
                    E004: "Input is neither a string nor an array of strings.",
                    E005: "Input is empty.",
                    E006: "Unexpected early end of program.",
                    E007: "Missing \"use strict\" statement.",
                    E008: "Strict violation.",
                    E009: "Option 'validthis' can't be used in a global scope.",
                    E010: "'with' is not allowed in strict mode.",
                    E011: "'{a}' has already been declared.",
                    E012: "const '{a}' is initialized to 'undefined'.",
                    E013: "Attempting to override '{a}' which is a constant.",
                    E014: "A regular expression literal can be confused with '/='.",
                    E015: "Unclosed regular expression.",
                    E016: "Invalid regular expression.",
                    E017: "Unclosed comment.",
                    E018: "Unbegun comment.",
                    E019: "Unmatched '{a}'.",
                    E020: "Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.",
                    E021: "Expected '{a}' and instead saw '{b}'.",
                    E022: "Line breaking error '{a}'.",
                    E023: "Missing '{a}'.",
                    E024: "Unexpected '{a}'.",
                    E025: "Missing ':' on a case clause.",
                    E026: "Missing '}' to match '{' from line {a}.",
                    E027: "Missing ']' to match '[' from line {a}.",
                    E028: "Illegal comma.",
                    E029: "Unclosed string.",
                    E030: "Expected an identifier and instead saw '{a}'.",
                    E031: "Bad assignment.", // FIXME: Rephrase
                    E032: "Expected a small integer or 'false' and instead saw '{a}'.",
                    E033: "Expected an operator and instead saw '{a}'.",
                    E034: "get/set are ES5 features.",
                    E035: "Missing property name.",
                    E036: "Expected to see a statement and instead saw a block.",
                    E037: null,
                    E038: null,
                    E039: "Function declarations are not invocable. Wrap the whole function invocation in parens.",
                    E040: "Each value should have its own case label.",
                    E041: "Unrecoverable syntax error.",
                    E042: "Stopping.",
                    E043: "Too many errors.",
                    E044: null,
                    E045: "Invalid for each loop.",
                    E046: "A yield statement shall be within a generator function (with syntax: `function*`)",
                    E047: null,
                    E048: "{a} declaration not directly within block.",
                    E049: "A {a} cannot be named '{b}'.",
                    E050: "Mozilla requires the yield expression to be parenthesized here.",
                    E051: null,
                    E052: "Unclosed template literal.",
                    E053: "Export declaration must be in global scope.",
                    E054: "Class properties must be methods. Expected '(' but instead saw '{a}'.",
                    E055: "The '{a}' option cannot be set after any executable code.",
                    E056: "'{a}' was used before it was declared, which is illegal for '{b}' variables.",
                    E057: "Invalid meta property: '{a}.{b}'.",
                    E058: "Missing semicolon."
                };

                var warnings = {
                    W001: "'hasOwnProperty' is a really bad name.",
                    W002: "Value of '{a}' may be overwritten in IE 8 and earlier.",
                    W003: "'{a}' was used before it was defined.",
                    W004: "'{a}' is already defined.",
                    W005: "A dot following a number can be confused with a decimal point.",
                    W006: "Confusing minuses.",
                    W007: "Confusing plusses.",
                    W008: "A leading decimal point can be confused with a dot: '{a}'.",
                    W009: "The array literal notation [] is preferable.",
                    W010: "The object literal notation {} is preferable.",
                    W011: null,
                    W012: null,
                    W013: null,
                    W014: "Bad line breaking before '{a}'.",
                    W015: null,
                    W016: "Unexpected use of '{a}'.",
                    W017: "Bad operand.",
                    W018: "Confusing use of '{a}'.",
                    W019: "Use the isNaN function to compare with NaN.",
                    W020: "Read only.",
                    W021: "Reassignment of '{a}', which is is a {b}. " +
                        "Use 'var' or 'let' to declare bindings that may change.",
                    W022: "Do not assign to the exception parameter.",
                    W023: "Expected an identifier in an assignment and instead saw a function invocation.",
                    W024: "Expected an identifier and instead saw '{a}' (a reserved word).",
                    W025: "Missing name in function declaration.",
                    W026: "Inner functions should be listed at the top of the outer function.",
                    W027: "Unreachable '{a}' after '{b}'.",
                    W028: "Label '{a}' on {b} statement.",
                    W030: "Expected an assignment or function call and instead saw an expression.",
                    W031: "Do not use 'new' for side effects.",
                    W032: "Unnecessary semicolon.",
                    W033: "Missing semicolon.",
                    W034: "Unnecessary directive \"{a}\".",
                    W035: "Empty block.",
                    W036: "Unexpected /*member '{a}'.",
                    W037: "'{a}' is a statement label.",
                    W038: "'{a}' used out of scope.",
                    W039: "'{a}' is not allowed.",
                    W040: "Possible strict violation.",
                    W041: "Use '{a}' to compare with '{b}'.",
                    W042: "Avoid EOL escaping.",
                    W043: "Bad escaping of EOL. Use option multistr if needed.",
                    W044: "Bad or unnecessary escaping.",
                    /* TODO(caitp): remove W044 */
                    W045: "Bad number '{a}'.",
                    W046: "Don't use extra leading zeros '{a}'.",
                    W047: "A trailing decimal point can be confused with a dot: '{a}'.",
                    W048: "Unexpected control character in regular expression.",
                    W049: "Unexpected escaped character '{a}' in regular expression.",
                    W050: "JavaScript URL.",
                    W051: "Variables should not be deleted.",
                    W052: "Unexpected '{a}'.",
                    W053: "Do not use {a} as a constructor.",
                    W054: "The Function constructor is a form of eval.",
                    W055: "A constructor name should start with an uppercase letter.",
                    W056: "Bad constructor.",
                    W057: "Weird construction. Is 'new' necessary?",
                    W058: "Missing '()' invoking a constructor.",
                    W059: "Avoid arguments.{a}.",
                    W060: "document.write can be a form of eval.",
                    W061: "eval can be harmful.",
                    W062: "Wrap an immediate function invocation in parens " +
                        "to assist the reader in understanding that the expression " +
                        "is the result of a function, and not the function itself.",
                    W063: "Math is not a function.",
                    W064: "Missing 'new' prefix when invoking a constructor.",
                    W065: "Missing radix parameter.",
                    W066: "Implied eval. Consider passing a function instead of a string.",
                    W067: "Bad invocation.",
                    W068: "Wrapping non-IIFE function literals in parens is unnecessary.",
                    W069: "['{a}'] is better written in dot notation.",
                    W070: "Extra comma. (it breaks older versions of IE)",
                    W071: "This function has too many statements. ({a})",
                    W072: "This function has too many parameters. ({a})",
                    W073: "Blocks are nested too deeply. ({a})",
                    W074: "This function's cyclomatic complexity is too high. ({a})",
                    W075: "Duplicate {a} '{b}'.",
                    W076: "Unexpected parameter '{a}' in get {b} function.",
                    W077: "Expected a single parameter in set {a} function.",
                    W078: "Setter is defined without getter.",
                    W079: "Redefinition of '{a}'.",
                    W080: "It's not necessary to initialize '{a}' to 'undefined'.",
                    W081: null,
                    W082: "Function declarations should not be placed in blocks. " +
                        "Use a function expression or move the statement to the top of " +
                        "the outer function.",
                    W083: "Don't make functions within a loop.",
                    W084: "Assignment in conditional expression",
                    W085: "Don't use 'with'.",
                    W086: "Expected a 'break' statement before '{a}'.",
                    W087: "Forgotten 'debugger' statement?",
                    W088: "Creating global 'for' variable. Should be 'for (var {a} ...'.",
                    W089: "The body of a for in should be wrapped in an if statement to filter " +
                        "unwanted properties from the prototype.",
                    W090: "'{a}' is not a statement label.",
                    W091: null,
                    W093: "Did you mean to return a conditional instead of an assignment?",
                    W094: "Unexpected comma.",
                    W095: "Expected a string and instead saw {a}.",
                    W096: "The '{a}' key may produce unexpected results.",
                    W097: "Use the function form of \"use strict\".",
                    W098: "'{a}' is defined but never used.",
                    W099: null,
                    W100: "This character may get silently deleted by one or more browsers.",
                    W101: "Line is too long.",
                    W102: null,
                    W103: "The '{a}' property is deprecated.",
                    W104: "'{a}' is available in ES{b} (use 'esversion: {b}') or Mozilla JS extensions (use moz).",
                    W105: "Unexpected {a} in '{b}'.",
                    W106: "Identifier '{a}' is not in camel case.",
                    W107: "Script URL.",
                    W108: "Strings must use doublequote.",
                    W109: "Strings must use singlequote.",
                    W110: "Mixed double and single quotes.",
                    W112: "Unclosed string.",
                    W113: "Control character in string: {a}.",
                    W114: "Avoid {a}.",
                    W115: "Octal literals are not allowed in strict mode.",
                    W116: "Expected '{a}' and instead saw '{b}'.",
                    W117: "'{a}' is not defined.",
                    W118: "'{a}' is only available in Mozilla JavaScript extensions (use moz option).",
                    W119: "'{a}' is only available in ES{b} (use 'esversion: {b}').",
                    W120: "You might be leaking a variable ({a}) here.",
                    W121: "Extending prototype of native object: '{a}'.",
                    W122: "Invalid typeof value '{a}'",
                    W123: "'{a}' is already defined in outer scope.",
                    W124: "A generator function shall contain a yield statement.",
                    W125: "This line contains non-breaking spaces: http://jshint.com/doc/options/#nonbsp",
                    W126: "Unnecessary grouping operator.",
                    W127: "Unexpected use of a comma operator.",
                    W128: "Empty array elements require elision=true.",
                    W129: "'{a}' is defined in a future version of JavaScript. Use a " +
                        "different variable name to avoid migration issues.",
                    W130: "Invalid element after rest element.",
                    W131: "Invalid parameter after rest parameter.",
                    W132: "`var` declarations are forbidden. Use `let` or `const` instead.",
                    W133: "Invalid for-{a} loop left-hand-side: {b}.",
                    W134: "The '{a}' option is only available when linting ECMAScript {b} code.",
                    W135: "{a} may not be supported by non-browser environments.",
                    W136: "'{a}' must be in function scope.",
                    W137: "Empty destructuring.",
                    W138: "Regular parameters should not come after default parameters."
                };

                var info = {
                    I001: "Comma warnings can be turned off with 'laxcomma'.",
                    I002: null,
                    I003: "ES5 option is now set per default"
                };

                exports.errors = {};
                exports.warnings = {};
                exports.info = {};

                _.each(errors, function(desc, code) {
                    exports.errors[code] = {
                        code: code,
                        desc: desc
                    };
                });

                _.each(warnings, function(desc, code) {
                    exports.warnings[code] = {
                        code: code,
                        desc: desc
                    };
                });

                _.each(info, function(desc, code) {
                    exports.info[code] = {
                        code: code,
                        desc: desc
                    };
                });

            }, {
                "../lodash": "/node_modules/jshint/lodash.js"
            }],
            "/node_modules/jshint/src/name-stack.js": [function(_dereq_, module, exports) {
                "use strict";

                function NameStack() {
                    this._stack = [];
                }

                Object.defineProperty(NameStack.prototype, "length", {
                    get: function() {
                        return this._stack.length;
                    }
                });
                NameStack.prototype.push = function() {
                    this._stack.push(null);
                };
                NameStack.prototype.pop = function() {
                    this._stack.pop();
                };
                NameStack.prototype.set = function(token) {
                    this._stack[this.length - 1] = token;
                };
                NameStack.prototype.infer = function() {
                    var nameToken = this._stack[this.length - 1];
                    var prefix = "";
                    var type;
                    if (!nameToken || nameToken.type === "class") {
                        nameToken = this._stack[this.length - 2];
                    }

                    if (!nameToken) {
                        return "(empty)";
                    }

                    type = nameToken.type;

                    if (type !== "(string)" && type !== "(number)" && type !== "(identifier)" && type !== "default") {
                        return "(expression)";
                    }

                    if (nameToken.accessorType) {
                        prefix = nameToken.accessorType + " ";
                    }

                    return prefix + nameToken.value;
                };

                module.exports = NameStack;

            }, {}],
            "/node_modules/jshint/src/options.js": [function(_dereq_, module, exports) {
                "use strict";
                exports.bool = {
                    enforcing: {
                        bitwise: true,
                        freeze: true,
                        camelcase: true,
                        curly: true,
                        eqeqeq: true,
                        futurehostile: true,
                        notypeof: true,
                        es3: true,
                        es5: true,
                        forin: true,
                        funcscope: true,
                        immed: true,
                        iterator: true,
                        newcap: true,
                        noarg: true,
                        nocomma: true,
                        noempty: true,
                        nonbsp: true,
                        nonew: true,
                        undef: true,
                        singleGroups: false,
                        varstmt: false,
                        enforceall: false
                    },
                    relaxing: {
                        asi: true,
                        multistr: true,
                        debug: true,
                        boss: true,
                        evil: true,
                        globalstrict: true,
                        plusplus: true,
                        proto: true,
                        scripturl: true,
                        sub: true,
                        supernew: true,
                        laxbreak: true,
                        laxcomma: true,
                        validthis: true,
                        withstmt: true,
                        moz: true,
                        noyield: true,
                        eqnull: true,
                        lastsemic: true,
                        loopfunc: true,
                        expr: true,
                        esnext: true,
                        elision: true,
                    },
                    environments: {
                        mootools: true,
                        couch: true,
                        jasmine: true,
                        jquery: true,
                        node: true,
                        qunit: true,
                        rhino: true,
                        shelljs: true,
                        prototypejs: true,
                        yui: true,
                        mocha: true,
                        module: true,
                        wsh: true,
                        worker: true,
                        nonstandard: true,
                        browser: true,
                        browserify: true,
                        devel: true,
                        dojo: true,
                        typed: true,
                        phantom: true
                    },
                    obsolete: {
                        onecase: true, // if one case switch statements should be allowed
                        regexp: true, // if the . should not be allowed in regexp literals
                        regexdash: true // if unescaped first/last dash (-) inside brackets
                    }
                };
                exports.val = {
                    maxlen: false,
                    indent: false,
                    maxerr: false,
                    predef: false,
                    globals: false,
                    quotmark: false,

                    scope: false,
                    maxstatements: false,
                    maxdepth: false,
                    maxparams: false,
                    maxcomplexity: false,
                    shadow: false,
                    strict: true,
                    unused: true,
                    latedef: false,

                    ignore: false, // start/end ignoring lines of code, bypassing the lexer

                    ignoreDelimiters: false, // array of start/end delimiters used to ignore
                    esversion: 5
                };
                exports.inverted = {
                    bitwise: true,
                    forin: true,
                    newcap: true,
                    plusplus: true,
                    regexp: true,
                    undef: true,
                    eqeqeq: true,
                    strict: true
                };

                exports.validNames = Object.keys(exports.val)
                    .concat(Object.keys(exports.bool.relaxing))
                    .concat(Object.keys(exports.bool.enforcing))
                    .concat(Object.keys(exports.bool.obsolete))
                    .concat(Object.keys(exports.bool.environments));
                exports.renamed = {
                    eqeq: "eqeqeq",
                    windows: "wsh",
                    sloppy: "strict"
                };

                exports.removed = {
                    nomen: true,
                    onevar: true,
                    passfail: true,
                    white: true,
                    gcl: true,
                    smarttabs: true,
                    trailing: true
                };
                exports.noenforceall = {
                    varstmt: true,
                    strict: true
                };

            }, {}],
            "/node_modules/jshint/src/reg.js": [function(_dereq_, module, exports) {

                "use strict";
                exports.unsafeString =
                    /@cc|<\/?|script|\]\s*\]|<\s*!|&lt/i;
                exports.unsafeChars =
                    /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
                exports.needEsc =
                    /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;

                exports.needEscGlobal =
                    /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
                exports.starSlash = /\*\//;
                exports.identifier = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/;
                exports.javascriptURL = /^(?:javascript|jscript|ecmascript|vbscript|livescript)\s*:/i;
                exports.fallsThrough = /^\s*falls?\sthrough\s*$/;
                exports.maxlenException = /^(?:(?:\/\/|\/\*|\*) ?)?[^ ]+$/;

            }, {}],
            "/node_modules/jshint/src/scope-manager.js": [function(_dereq_, module, exports) {
                "use strict";

                var _ = _dereq_("../lodash");
                var events = _dereq_("events");
                var marker = {};
                var scopeManager = function(state, predefined, exported, declared) {

                    var _current;
                    var _scopeStack = [];

                    function _newScope(type) {
                        _current = {
                            "(labels)": Object.create(null),
                            "(usages)": Object.create(null),
                            "(breakLabels)": Object.create(null),
                            "(parent)": _current,
                            "(type)": type,
                            "(params)": (type === "functionparams" || type === "catchparams") ? [] : null
                        };
                        _scopeStack.push(_current);
                    }

                    _newScope("global");
                    _current["(predefined)"] = predefined;

                    var _currentFunctBody = _current; // this is the block after the params = function

                    var usedPredefinedAndGlobals = Object.create(null);
                    var impliedGlobals = Object.create(null);
                    var unuseds = [];
                    var emitter = new events.EventEmitter();

                    function warning(code, token) {
                        emitter.emit("warning", {
                            code: code,
                            token: token,
                            data: _.slice(arguments, 2)
                        });
                    }

                    function error(code, token) {
                        emitter.emit("warning", {
                            code: code,
                            token: token,
                            data: _.slice(arguments, 2)
                        });
                    }

                    function _setupUsages(labelName) {
                        if (!_current["(usages)"][labelName]) {
                            _current["(usages)"][labelName] = {
                                "(modified)": [],
                                "(reassigned)": [],
                                "(tokens)": []
                            };
                        }
                    }

                    var _getUnusedOption = function(unused_opt) {
                        if (unused_opt === undefined) {
                            unused_opt = state.option.unused;
                        }

                        if (unused_opt === true) {
                            unused_opt = "last-param";
                        }

                        return unused_opt;
                    };

                    var _warnUnused = function(name, tkn, type, unused_opt) {
                        var line = tkn.line;
                        var chr = tkn.from;
                        var raw_name = tkn.raw_text || name;

                        unused_opt = _getUnusedOption(unused_opt);

                        var warnable_types = {
                            "vars": ["var"],
                            "last-param": ["var", "param"],
                            "strict": ["var", "param", "last-param"]
                        };

                        if (unused_opt) {
                            if (warnable_types[unused_opt] && warnable_types[unused_opt].indexOf(type) !== -1) {
                                warning("W098", {
                                    line: line,
                                    from: chr
                                }, raw_name);
                            }
                        }
                        if (unused_opt || type === "var") {
                            unuseds.push({
                                name: name,
                                line: line,
                                character: chr
                            });
                        }
                    };

                    function _checkForUnused() {
                        if (_current["(type)"] === "functionparams") {
                            _checkParams();
                            return;
                        }
                        var curentLabels = _current["(labels)"];
                        for (var labelName in curentLabels) {
                            if (curentLabels[labelName]) {
                                if (curentLabels[labelName]["(type)"] !== "exception" &&
                                    curentLabels[labelName]["(unused)"]) {
                                    _warnUnused(labelName, curentLabels[labelName]["(token)"], "var");
                                }
                            }
                        }
                    }

                    function _checkParams() {
                        var params = _current["(params)"];

                        if (!params) {
                            return;
                        }

                        var param = params.pop();
                        var unused_opt;

                        while (param) {
                            var label = _current["(labels)"][param];

                            unused_opt = _getUnusedOption(state.funct["(unusedOption)"]);
                            if (param === "undefined")
                                return;

                            if (label["(unused)"]) {
                                _warnUnused(param, label["(token)"], "param", state.funct["(unusedOption)"]);
                            } else if (unused_opt === "last-param") {
                                return;
                            }

                            param = params.pop();
                        }
                    }

                    function _getLabel(labelName) {
                        for (var i = _scopeStack.length - 1; i >= 0; --i) {
                            var scopeLabels = _scopeStack[i]["(labels)"];
                            if (scopeLabels[labelName]) {
                                return scopeLabels;
                            }
                        }
                    }

                    function usedSoFarInCurrentFunction(labelName) {
                        for (var i = _scopeStack.length - 1; i >= 0; i--) {
                            var current = _scopeStack[i];
                            if (current["(usages)"][labelName]) {
                                return current["(usages)"][labelName];
                            }
                            if (current === _currentFunctBody) {
                                break;
                            }
                        }
                        return false;
                    }

                    function _checkOuterShadow(labelName, token) {
                        if (state.option.shadow !== "outer") {
                            return;
                        }

                        var isGlobal = _currentFunctBody["(type)"] === "global",
                            isNewFunction = _current["(type)"] === "functionparams";

                        var outsideCurrentFunction = !isGlobal;
                        for (var i = 0; i < _scopeStack.length; i++) {
                            var stackItem = _scopeStack[i];

                            if (!isNewFunction && _scopeStack[i + 1] === _currentFunctBody) {
                                outsideCurrentFunction = false;
                            }
                            if (outsideCurrentFunction && stackItem["(labels)"][labelName]) {
                                warning("W123", token, labelName);
                            }
                            if (stackItem["(breakLabels)"][labelName]) {
                                warning("W123", token, labelName);
                            }
                        }
                    }

                    function _latedefWarning(type, labelName, token) {
                        if (state.option.latedef) {
                            if ((state.option.latedef === true && type === "function") ||
                                type !== "function") {
                                warning("W003", token, labelName);
                            }
                        }
                    }

                    var scopeManagerInst = {

                        on: function(names, listener) {
                            names.split(" ").forEach(function(name) {
                                emitter.on(name, listener);
                            });
                        },

                        isPredefined: function(labelName) {
                            return !this.has(labelName) && _.has(_scopeStack[0]["(predefined)"], labelName);
                        },
                        stack: function(type) {
                            var previousScope = _current;
                            _newScope(type);

                            if (!type && previousScope["(type)"] === "functionparams") {

                                _current["(isFuncBody)"] = true;
                                _current["(context)"] = _currentFunctBody;
                                _currentFunctBody = _current;
                            }
                        },

                        unstack: function() {
                            var subScope = _scopeStack.length > 1 ? _scopeStack[_scopeStack.length - 2] : null;
                            var isUnstackingFunctionBody = _current === _currentFunctBody,
                                isUnstackingFunctionParams = _current["(type)"] === "functionparams",
                                isUnstackingFunctionOuter = _current["(type)"] === "functionouter";

                            var i, j;
                            var currentUsages = _current["(usages)"];
                            var currentLabels = _current["(labels)"];
                            var usedLabelNameList = Object.keys(currentUsages);

                            if (currentUsages.__proto__ && usedLabelNameList.indexOf("__proto__") === -1) {
                                usedLabelNameList.push("__proto__");
                            }

                            for (i = 0; i < usedLabelNameList.length; i++) {
                                var usedLabelName = usedLabelNameList[i];

                                var usage = currentUsages[usedLabelName];
                                var usedLabel = currentLabels[usedLabelName];
                                if (usedLabel) {
                                    var usedLabelType = usedLabel["(type)"];

                                    if (usedLabel["(useOutsideOfScope)"] && !state.option.funcscope) {
                                        var usedTokens = usage["(tokens)"];
                                        if (usedTokens) {
                                            for (j = 0; j < usedTokens.length; j++) {
                                                if (usedLabel["(function)"] === usedTokens[j]["(function)"]) {
                                                    error("W038", usedTokens[j], usedLabelName);
                                                }
                                            }
                                        }
                                    }
                                    _current["(labels)"][usedLabelName]["(unused)"] = false;
                                    if (usedLabelType === "const" && usage["(modified)"]) {
                                        for (j = 0; j < usage["(modified)"].length; j++) {
                                            error("E013", usage["(modified)"][j], usedLabelName);
                                        }
                                    }
                                    if ((usedLabelType === "function" || usedLabelType === "class") &&
                                        usage["(reassigned)"]) {
                                        for (j = 0; j < usage["(reassigned)"].length; j++) {
                                            error("W021", usage["(reassigned)"][j], usedLabelName, usedLabelType);
                                        }
                                    }
                                    continue;
                                }

                                if (isUnstackingFunctionOuter) {
                                    state.funct["(isCapturing)"] = true;
                                }

                                if (subScope) {
                                    if (!subScope["(usages)"][usedLabelName]) {
                                        subScope["(usages)"][usedLabelName] = usage;
                                        if (isUnstackingFunctionBody) {
                                            subScope["(usages)"][usedLabelName]["(onlyUsedSubFunction)"] = true;
                                        }
                                    } else {
                                        var subScopeUsage = subScope["(usages)"][usedLabelName];
                                        subScopeUsage["(modified)"] = subScopeUsage["(modified)"].concat(usage["(modified)"]);
                                        subScopeUsage["(tokens)"] = subScopeUsage["(tokens)"].concat(usage["(tokens)"]);
                                        subScopeUsage["(reassigned)"] =
                                            subScopeUsage["(reassigned)"].concat(usage["(reassigned)"]);
                                        subScopeUsage["(onlyUsedSubFunction)"] = false;
                                    }
                                } else {
                                    if (typeof _current["(predefined)"][usedLabelName] === "boolean") {
                                        delete declared[usedLabelName];
                                        usedPredefinedAndGlobals[usedLabelName] = marker;
                                        if (_current["(predefined)"][usedLabelName] === false && usage["(reassigned)"]) {
                                            for (j = 0; j < usage["(reassigned)"].length; j++) {
                                                warning("W020", usage["(reassigned)"][j]);
                                            }
                                        }
                                    } else {
                                        if (usage["(tokens)"]) {
                                            for (j = 0; j < usage["(tokens)"].length; j++) {
                                                var undefinedToken = usage["(tokens)"][j];
                                                if (!undefinedToken.forgiveUndef) {
                                                    if (state.option.undef && !undefinedToken.ignoreUndef) {
                                                        warning("W117", undefinedToken, usedLabelName);
                                                    }
                                                    if (impliedGlobals[usedLabelName]) {
                                                        impliedGlobals[usedLabelName].line.push(undefinedToken.line);
                                                    } else {
                                                        impliedGlobals[usedLabelName] = {
                                                            name: usedLabelName,
                                                            line: [undefinedToken.line]
                                                        };
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            if (!subScope) {
                                Object.keys(declared)
                                    .forEach(function(labelNotUsed) {
                                        _warnUnused(labelNotUsed, declared[labelNotUsed], "var");
                                    });
                            }
                            if (subScope && !isUnstackingFunctionBody &&
                                !isUnstackingFunctionParams && !isUnstackingFunctionOuter) {
                                var labelNames = Object.keys(currentLabels);
                                for (i = 0; i < labelNames.length; i++) {

                                    var defLabelName = labelNames[i];
                                    if (!currentLabels[defLabelName]["(blockscoped)"] &&
                                        currentLabels[defLabelName]["(type)"] !== "exception" &&
                                        !this.funct.has(defLabelName, {
                                            excludeCurrent: true
                                        })) {
                                        subScope["(labels)"][defLabelName] = currentLabels[defLabelName];
                                        if (_currentFunctBody["(type)"] !== "global") {
                                            subScope["(labels)"][defLabelName]["(useOutsideOfScope)"] = true;
                                        }
                                        delete currentLabels[defLabelName];
                                    }
                                }
                            }

                            _checkForUnused();

                            _scopeStack.pop();
                            if (isUnstackingFunctionBody) {
                                _currentFunctBody = _scopeStack[_.findLastIndex(_scopeStack, function(scope) {
                                    return scope["(isFuncBody)"] || scope["(type)"] === "global";
                                })];
                            }

                            _current = subScope;
                        },
                        addParam: function(labelName, token, type) {
                            type = type || "param";

                            if (type === "exception") {
                                var previouslyDefinedLabelType = this.funct.labeltype(labelName);
                                if (previouslyDefinedLabelType && previouslyDefinedLabelType !== "exception") {
                                    if (!state.option.node) {
                                        warning("W002", state.tokens.next, labelName);
                                    }
                                }
                            }
                            if (_.has(_current["(labels)"], labelName)) {
                                _current["(labels)"][labelName].duplicated = true;
                            } else {
                                _checkOuterShadow(labelName, token, type);

                                _current["(labels)"][labelName] = {
                                    "(type)": type,
                                    "(token)": token,
                                    "(unused)": true
                                };

                                _current["(params)"].push(labelName);
                            }

                            if (_.has(_current["(usages)"], labelName)) {
                                var usage = _current["(usages)"][labelName];
                                if (usage["(onlyUsedSubFunction)"]) {
                                    _latedefWarning(type, labelName, token);
                                } else {
                                    warning("E056", token, labelName, type);
                                }
                            }
                        },

                        validateParams: function() {
                            if (_currentFunctBody["(type)"] === "global") {
                                return;
                            }

                            var isStrict = state.isStrict();
                            var currentFunctParamScope = _currentFunctBody["(parent)"];

                            if (!currentFunctParamScope["(params)"]) {
                                return;
                            }

                            currentFunctParamScope["(params)"].forEach(function(labelName) {
                                var label = currentFunctParamScope["(labels)"][labelName];

                                if (label && label.duplicated) {
                                    if (isStrict) {
                                        warning("E011", label["(token)"], labelName);
                                    } else if (state.option.shadow !== true) {
                                        warning("W004", label["(token)"], labelName);
                                    }
                                }
                            });
                        },

                        getUsedOrDefinedGlobals: function() {
                            var list = Object.keys(usedPredefinedAndGlobals);
                            if (usedPredefinedAndGlobals.__proto__ === marker &&
                                list.indexOf("__proto__") === -1) {
                                list.push("__proto__");
                            }

                            return list;
                        },
                        getImpliedGlobals: function() {
                            var values = _.values(impliedGlobals);
                            var hasProto = false;
                            if (impliedGlobals.__proto__) {
                                hasProto = values.some(function(value) {
                                    return value.name === "__proto__";
                                });

                                if (!hasProto) {
                                    values.push(impliedGlobals.__proto__);
                                }
                            }

                            return values;
                        },
                        getUnuseds: function() {
                            return unuseds;
                        },

                        has: function(labelName) {
                            return Boolean(_getLabel(labelName));
                        },

                        labeltype: function(labelName) {
                            var scopeLabels = _getLabel(labelName);
                            if (scopeLabels) {
                                return scopeLabels[labelName]["(type)"];
                            }
                            return null;
                        },
                        addExported: function(labelName) {
                            var globalLabels = _scopeStack[0]["(labels)"];
                            if (_.has(declared, labelName)) {
                                delete declared[labelName];
                            } else if (_.has(globalLabels, labelName)) {
                                globalLabels[labelName]["(unused)"] = false;
                            } else {
                                for (var i = 1; i < _scopeStack.length; i++) {
                                    var scope = _scopeStack[i];
                                    if (!scope["(type)"]) {
                                        if (_.has(scope["(labels)"], labelName) &&
                                            !scope["(labels)"][labelName]["(blockscoped)"]) {
                                            scope["(labels)"][labelName]["(unused)"] = false;
                                            return;
                                        }
                                    } else {
                                        break;
                                    }
                                }
                                exported[labelName] = true;
                            }
                        },
                        setExported: function(labelName, token) {
                            this.block.use(labelName, token);
                        },
                        addlabel: function(labelName, opts) {

                            var type = opts.type;
                            var token = opts.token;
                            var isblockscoped = type === "let" || type === "const" || type === "class";
                            var isexported = (isblockscoped ? _current : _currentFunctBody)["(type)"] === "global" &&
                                _.has(exported, labelName);
                            _checkOuterShadow(labelName, token, type);
                            if (isblockscoped) {

                                var declaredInCurrentScope = _current["(labels)"][labelName];
                                if (!declaredInCurrentScope && _current === _currentFunctBody &&
                                    _current["(type)"] !== "global") {
                                    declaredInCurrentScope = !!_currentFunctBody["(parent)"]["(labels)"][labelName];
                                }
                                if (!declaredInCurrentScope && _current["(usages)"][labelName]) {
                                    var usage = _current["(usages)"][labelName];
                                    if (usage["(onlyUsedSubFunction)"]) {
                                        _latedefWarning(type, labelName, token);
                                    } else {
                                        warning("E056", token, labelName, type);
                                    }
                                }
                                if (declaredInCurrentScope) {
                                    warning("E011", token, labelName);
                                } else if (state.option.shadow === "outer") {
                                    if (scopeManagerInst.funct.has(labelName)) {
                                        warning("W004", token, labelName);
                                    }
                                }

                                scopeManagerInst.block.add(labelName, type, token, !isexported);

                            } else {

                                var declaredInCurrentFunctionScope = scopeManagerInst.funct.has(labelName);
                                if (!declaredInCurrentFunctionScope && usedSoFarInCurrentFunction(labelName)) {
                                    _latedefWarning(type, labelName, token);
                                }
                                if (scopeManagerInst.funct.has(labelName, {
                                        onlyBlockscoped: true
                                    })) {
                                    warning("E011", token, labelName);
                                } else if (state.option.shadow !== true) {
                                    if (declaredInCurrentFunctionScope && labelName !== "__proto__") {
                                        if (_currentFunctBody["(type)"] !== "global") {
                                            warning("W004", token, labelName);
                                        }
                                    }
                                }

                                scopeManagerInst.funct.add(labelName, type, token, !isexported);

                                if (_currentFunctBody["(type)"] === "global") {
                                    usedPredefinedAndGlobals[labelName] = marker;
                                }
                            }
                        },

                        funct: {
                            labeltype: function(labelName, options) {
                                var onlyBlockscoped = options && options.onlyBlockscoped;
                                var excludeParams = options && options.excludeParams;
                                var currentScopeIndex = _scopeStack.length - (options && options.excludeCurrent ? 2 : 1);
                                for (var i = currentScopeIndex; i >= 0; i--) {
                                    var current = _scopeStack[i];
                                    if (current["(labels)"][labelName] &&
                                        (!onlyBlockscoped || current["(labels)"][labelName]["(blockscoped)"])) {
                                        return current["(labels)"][labelName]["(type)"];
                                    }
                                    var scopeCheck = excludeParams ? _scopeStack[i - 1] : current;
                                    if (scopeCheck && scopeCheck["(type)"] === "functionparams") {
                                        return null;
                                    }
                                }
                                return null;
                            },
                            hasBreakLabel: function(labelName) {
                                for (var i = _scopeStack.length - 1; i >= 0; i--) {
                                    var current = _scopeStack[i];

                                    if (current["(breakLabels)"][labelName]) {
                                        return true;
                                    }
                                    if (current["(type)"] === "functionparams") {
                                        return false;
                                    }
                                }
                                return false;
                            },
                            has: function(labelName, options) {
                                return Boolean(this.labeltype(labelName, options));
                            },
                            add: function(labelName, type, tok, unused) {
                                _current["(labels)"][labelName] = {
                                    "(type)": type,
                                    "(token)": tok,
                                    "(blockscoped)": false,
                                    "(function)": _currentFunctBody,
                                    "(unused)": unused
                                };
                            }
                        },

                        block: {
                            isGlobal: function() {
                                return _current["(type)"] === "global";
                            },

                            use: function(labelName, token) {
                                var paramScope = _currentFunctBody["(parent)"];
                                if (paramScope && paramScope["(labels)"][labelName] &&
                                    paramScope["(labels)"][labelName]["(type)"] === "param") {
                                    if (!scopeManagerInst.funct.has(labelName, {
                                            excludeParams: true,
                                            onlyBlockscoped: true
                                        })) {
                                        paramScope["(labels)"][labelName]["(unused)"] = false;
                                    }
                                }

                                if (token && (state.ignored.W117 || state.option.undef === false)) {
                                    token.ignoreUndef = true;
                                }

                                _setupUsages(labelName);

                                if (token) {
                                    token["(function)"] = _currentFunctBody;
                                    _current["(usages)"][labelName]["(tokens)"].push(token);
                                }
                            },

                            reassign: function(labelName, token) {

                                this.modify(labelName, token);

                                _current["(usages)"][labelName]["(reassigned)"].push(token);
                            },

                            modify: function(labelName, token) {

                                _setupUsages(labelName);

                                _current["(usages)"][labelName]["(modified)"].push(token);
                            },
                            add: function(labelName, type, tok, unused) {
                                _current["(labels)"][labelName] = {
                                    "(type)": type,
                                    "(token)": tok,
                                    "(blockscoped)": true,
                                    "(unused)": unused
                                };
                            },

                            addBreakLabel: function(labelName, opts) {
                                var token = opts.token;
                                if (scopeManagerInst.funct.hasBreakLabel(labelName)) {
                                    warning("E011", token, labelName);
                                } else if (state.option.shadow === "outer") {
                                    if (scopeManagerInst.funct.has(labelName)) {
                                        warning("W004", token, labelName);
                                    } else {
                                        _checkOuterShadow(labelName, token);
                                    }
                                }
                                _current["(breakLabels)"][labelName] = token;
                            }
                        }
                    };
                    return scopeManagerInst;
                };

                module.exports = scopeManager;

            }, {
                "../lodash": "/node_modules/jshint/lodash.js",
                "events": "/node_modules/browserify/node_modules/events/events.js"
            }],
            "/node_modules/jshint/src/state.js": [function(_dereq_, module, exports) {
                "use strict";
                var NameStack = _dereq_("./name-stack.js");

                var state = {
                    syntax: {},
                    isStrict: function() {
                        return this.directive["use strict"] || this.inClassBody ||
                            this.option.module || this.option.strict === "implied";
                    },

                    inMoz: function() {
                        return this.option.moz;
                    },
                    inES6: function() {
                        return this.option.moz || this.option.esversion >= 6;
                    },
                    inES5: function(strict) {
                        if (strict) {
                            return (!this.option.esversion || this.option.esversion === 5) && !this.option.moz;
                        }
                        return !this.option.esversion || this.option.esversion >= 5 || this.option.moz;
                    },


                    reset: function() {
                        this.tokens = {
                            prev: null,
                            next: null,
                            curr: null
                        };

                        this.option = {};
                        this.funct = null;
                        this.ignored = {};
                        this.directive = {};
                        this.jsonMode = false;
                        this.jsonWarnings = [];
                        this.lines = [];
                        this.tab = "";
                        this.cache = {}; // Node.JS doesn't have Map. Sniff.
                        this.ignoredLines = {};
                        this.forinifcheckneeded = false;
                        this.nameStack = new NameStack();
                        this.inClassBody = false;
                    }
                };

                exports.state = state;

            }, {
                "./name-stack.js": "/node_modules/jshint/src/name-stack.js"
            }],
            "/node_modules/jshint/src/style.js": [function(_dereq_, module, exports) {
                "use strict";

                exports.register = function(linter) {

                    linter.on("Identifier", function style_scanProto(data) {
                        if (linter.getOption("proto")) {
                            return;
                        }

                        if (data.name === "__proto__") {
                            linter.warn("W103", {
                                line: data.line,
                                char: data.char,
                                data: [data.name, "6"]
                            });
                        }
                    });

                    linter.on("Identifier", function style_scanIterator(data) {
                        if (linter.getOption("iterator")) {
                            return;
                        }

                        if (data.name === "__iterator__") {
                            linter.warn("W103", {
                                line: data.line,
                                char: data.char,
                                data: [data.name]
                            });
                        }
                    });

                    linter.on("Identifier", function style_scanCamelCase(data) {
                        if (!linter.getOption("camelcase")) {
                            return;
                        }

                        if (data.name.replace(/^_+|_+$/g, "").indexOf("_") > -1 && !data.name.match(/^[A-Z0-9_]*$/)) {
                            linter.warn("W106", {
                                line: data.line,
                                char: data.from,
                                data: [data.name]
                            });
                        }
                    });

                    linter.on("String", function style_scanQuotes(data) {
                        var quotmark = linter.getOption("quotmark");
                        var code;

                        if (!quotmark) {
                            return;
                        }

                        if (quotmark === "single" && data.quote !== "'") {
                            code = "W109";
                        }

                        if (quotmark === "double" && data.quote !== "\"") {
                            code = "W108";
                        }

                        if (quotmark === true) {
                            if (!linter.getCache("quotmark")) {
                                linter.setCache("quotmark", data.quote);
                            }

                            if (linter.getCache("quotmark") !== data.quote) {
                                code = "W110";
                            }
                        }

                        if (code) {
                            linter.warn(code, {
                                line: data.line,
                                char: data.char,
                            });
                        }
                    });

                    linter.on("Number", function style_scanNumbers(data) {
                        if (data.value.charAt(0) === ".") {
                            linter.warn("W008", {
                                line: data.line,
                                char: data.char,
                                data: [data.value]
                            });
                        }

                        if (data.value.substr(data.value.length - 1) === ".") {
                            linter.warn("W047", {
                                line: data.line,
                                char: data.char,
                                data: [data.value]
                            });
                        }

                        if (/^00+/.test(data.value)) {
                            linter.warn("W046", {
                                line: data.line,
                                char: data.char,
                                data: [data.value]
                            });
                        }
                    });

                    linter.on("String", function style_scanJavaScriptURLs(data) {
                        var re = /^(?:javascript|jscript|ecmascript|vbscript|livescript)\s*:/i;

                        if (linter.getOption("scripturl")) {
                            return;
                        }

                        if (re.test(data.value)) {
                            linter.warn("W107", {
                                line: data.line,
                                char: data.char
                            });
                        }
                    });
                };

            }, {}],
            "/node_modules/jshint/src/vars.js": [function(_dereq_, module, exports) {

                "use strict";

                exports.reservedVars = {
                    arguments: false,
                    NaN: false
                };

                exports.ecmaIdentifiers = {
                    3: {
                        Array: false,
                        Boolean: false,
                        Date: false,
                        decodeURI: false,
                        decodeURIComponent: false,
                        encodeURI: false,
                        encodeURIComponent: false,
                        Error: false,
                        "eval": false,
                        EvalError: false,
                        Function: false,
                        hasOwnProperty: false,
                        isFinite: false,
                        isNaN: false,
                        Math: false,
                        Number: false,
                        Object: false,
                        parseInt: false,
                        parseFloat: false,
                        RangeError: false,
                        ReferenceError: false,
                        RegExp: false,
                        String: false,
                        SyntaxError: false,
                        TypeError: false,
                        URIError: false
                    },
                    5: {
                        JSON: false
                    },
                    6: {
                        Map: false,
                        Promise: false,
                        Proxy: false,
                        Reflect: false,
                        Set: false,
                        Symbol: false,
                        WeakMap: false,
                        WeakSet: false
                    }
                };

                exports.browser = {
                    Audio: false,
                    Blob: false,
                    addEventListener: false,
                    applicationCache: false,
                    atob: false,
                    blur: false,
                    btoa: false,
                    cancelAnimationFrame: false,
                    CanvasGradient: false,
                    CanvasPattern: false,
                    CanvasRenderingContext2D: false,
                    CSS: false,
                    clearInterval: false,
                    clearTimeout: false,
                    close: false,
                    closed: false,
                    Comment: false,
                    CustomEvent: false,
                    DOMParser: false,
                    defaultStatus: false,
                    Document: false,
                    document: false,
                    DocumentFragment: false,
                    Element: false,
                    ElementTimeControl: false,
                    Event: false,
                    event: false,
                    fetch: false,
                    FileReader: false,
                    FormData: false,
                    focus: false,
                    frames: false,
                    getComputedStyle: false,
                    HTMLElement: false,
                    HTMLAnchorElement: false,
                    HTMLBaseElement: false,
                    HTMLBlockquoteElement: false,
                    HTMLBodyElement: false,
                    HTMLBRElement: false,
                    HTMLButtonElement: false,
                    HTMLCanvasElement: false,
                    HTMLCollection: false,
                    HTMLDirectoryElement: false,
                    HTMLDivElement: false,
                    HTMLDListElement: false,
                    HTMLFieldSetElement: false,
                    HTMLFontElement: false,
                    HTMLFormElement: false,
                    HTMLFrameElement: false,
                    HTMLFrameSetElement: false,
                    HTMLHeadElement: false,
                    HTMLHeadingElement: false,
                    HTMLHRElement: false,
                    HTMLHtmlElement: false,
                    HTMLIFrameElement: false,
                    HTMLImageElement: false,
                    HTMLInputElement: false,
                    HTMLIsIndexElement: false,
                    HTMLLabelElement: false,
                    HTMLLayerElement: false,
                    HTMLLegendElement: false,
                    HTMLLIElement: false,
                    HTMLLinkElement: false,
                    HTMLMapElement: false,
                    HTMLMenuElement: false,
                    HTMLMetaElement: false,
                    HTMLModElement: false,
                    HTMLObjectElement: false,
                    HTMLOListElement: false,
                    HTMLOptGroupElement: false,
                    HTMLOptionElement: false,
                    HTMLParagraphElement: false,
                    HTMLParamElement: false,
                    HTMLPreElement: false,
                    HTMLQuoteElement: false,
                    HTMLScriptElement: false,
                    HTMLSelectElement: false,
                    HTMLStyleElement: false,
                    HTMLTableCaptionElement: false,
                    HTMLTableCellElement: false,
                    HTMLTableColElement: false,
                    HTMLTableElement: false,
                    HTMLTableRowElement: false,
                    HTMLTableSectionElement: false,
                    HTMLTemplateElement: false,
                    HTMLTextAreaElement: false,
                    HTMLTitleElement: false,
                    HTMLUListElement: false,
                    HTMLVideoElement: false,
                    history: false,
                    Image: false,
                    Intl: false,
                    length: false,
                    localStorage: false,
                    location: false,
                    matchMedia: false,
                    MessageChannel: false,
                    MessageEvent: false,
                    MessagePort: false,
                    MouseEvent: false,
                    moveBy: false,
                    moveTo: false,
                    MutationObserver: false,
                    name: false,
                    Node: false,
                    NodeFilter: false,
                    NodeList: false,
                    Notification: false,
                    navigator: false,
                    onbeforeunload: true,
                    onblur: true,
                    onerror: true,
                    onfocus: true,
                    onload: true,
                    onresize: true,
                    onunload: true,
                    open: false,
                    openDatabase: false,
                    opener: false,
                    Option: false,
                    parent: false,
                    performance: false,
                    print: false,
                    Range: false,
                    requestAnimationFrame: false,
                    removeEventListener: false,
                    resizeBy: false,
                    resizeTo: false,
                    screen: false,
                    scroll: false,
                    scrollBy: false,
                    scrollTo: false,
                    sessionStorage: false,
                    setInterval: false,
                    setTimeout: false,
                    SharedWorker: false,
                    status: false,
                    SVGAElement: false,
                    SVGAltGlyphDefElement: false,
                    SVGAltGlyphElement: false,
                    SVGAltGlyphItemElement: false,
                    SVGAngle: false,
                    SVGAnimateColorElement: false,
                    SVGAnimateElement: false,
                    SVGAnimateMotionElement: false,
                    SVGAnimateTransformElement: false,
                    SVGAnimatedAngle: false,
                    SVGAnimatedBoolean: false,
                    SVGAnimatedEnumeration: false,
                    SVGAnimatedInteger: false,
                    SVGAnimatedLength: false,
                    SVGAnimatedLengthList: false,
                    SVGAnimatedNumber: false,
                    SVGAnimatedNumberList: false,
                    SVGAnimatedPathData: false,
                    SVGAnimatedPoints: false,
                    SVGAnimatedPreserveAspectRatio: false,
                    SVGAnimatedRect: false,
                    SVGAnimatedString: false,
                    SVGAnimatedTransformList: false,
                    SVGAnimationElement: false,
                    SVGCSSRule: false,
                    SVGCircleElement: false,
                    SVGClipPathElement: false,
                    SVGColor: false,
                    SVGColorProfileElement: false,
                    SVGColorProfileRule: false,
                    SVGComponentTransferFunctionElement: false,
                    SVGCursorElement: false,
                    SVGDefsElement: false,
                    SVGDescElement: false,
                    SVGDocument: false,
                    SVGElement: false,
                    SVGElementInstance: false,
                    SVGElementInstanceList: false,
                    SVGEllipseElement: false,
                    SVGExternalResourcesRequired: false,
                    SVGFEBlendElement: false,
                    SVGFEColorMatrixElement: false,
                    SVGFEComponentTransferElement: false,
                    SVGFECompositeElement: false,
                    SVGFEConvolveMatrixElement: false,
                    SVGFEDiffuseLightingElement: false,
                    SVGFEDisplacementMapElement: false,
                    SVGFEDistantLightElement: false,
                    SVGFEFloodElement: false,
                    SVGFEFuncAElement: false,
                    SVGFEFuncBElement: false,
                    SVGFEFuncGElement: false,
                    SVGFEFuncRElement: false,
                    SVGFEGaussianBlurElement: false,
                    SVGFEImageElement: false,
                    SVGFEMergeElement: false,
                    SVGFEMergeNodeElement: false,
                    SVGFEMorphologyElement: false,
                    SVGFEOffsetElement: false,
                    SVGFEPointLightElement: false,
                    SVGFESpecularLightingElement: false,
                    SVGFESpotLightElement: false,
                    SVGFETileElement: false,
                    SVGFETurbulenceElement: false,
                    SVGFilterElement: false,
                    SVGFilterPrimitiveStandardAttributes: false,
                    SVGFitToViewBox: false,
                    SVGFontElement: false,
                    SVGFontFaceElement: false,
                    SVGFontFaceFormatElement: false,
                    SVGFontFaceNameElement: false,
                    SVGFontFaceSrcElement: false,
                    SVGFontFaceUriElement: false,
                    SVGForeignObjectElement: false,
                    SVGGElement: false,
                    SVGGlyphElement: false,
                    SVGGlyphRefElement: false,
                    SVGGradientElement: false,
                    SVGHKernElement: false,
                    SVGICCColor: false,
                    SVGImageElement: false,
                    SVGLangSpace: false,
                    SVGLength: false,
                    SVGLengthList: false,
                    SVGLineElement: false,
                    SVGLinearGradientElement: false,
                    SVGLocatable: false,
                    SVGMPathElement: false,
                    SVGMarkerElement: false,
                    SVGMaskElement: false,
                    SVGMatrix: false,
                    SVGMetadataElement: false,
                    SVGMissingGlyphElement: false,
                    SVGNumber: false,
                    SVGNumberList: false,
                    SVGPaint: false,
                    SVGPathElement: false,
                    SVGPathSeg: false,
                    SVGPathSegArcAbs: false,
                    SVGPathSegArcRel: false,
                    SVGPathSegClosePath: false,
                    SVGPathSegCurvetoCubicAbs: false,
                    SVGPathSegCurvetoCubicRel: false,
                    SVGPathSegCurvetoCubicSmoothAbs: false,
                    SVGPathSegCurvetoCubicSmoothRel: false,
                    SVGPathSegCurvetoQuadraticAbs: false,
                    SVGPathSegCurvetoQuadraticRel: false,
                    SVGPathSegCurvetoQuadraticSmoothAbs: false,
                    SVGPathSegCurvetoQuadraticSmoothRel: false,
                    SVGPathSegLinetoAbs: false,
                    SVGPathSegLinetoHorizontalAbs: false,
                    SVGPathSegLinetoHorizontalRel: false,
                    SVGPathSegLinetoRel: false,
                    SVGPathSegLinetoVerticalAbs: false,
                    SVGPathSegLinetoVerticalRel: false,
                    SVGPathSegList: false,
                    SVGPathSegMovetoAbs: false,
                    SVGPathSegMovetoRel: false,
                    SVGPatternElement: false,
                    SVGPoint: false,
                    SVGPointList: false,
                    SVGPolygonElement: false,
                    SVGPolylineElement: false,
                    SVGPreserveAspectRatio: false,
                    SVGRadialGradientElement: false,
                    SVGRect: false,
                    SVGRectElement: false,
                    SVGRenderingIntent: false,
                    SVGSVGElement: false,
                    SVGScriptElement: false,
                    SVGSetElement: false,
                    SVGStopElement: false,
                    SVGStringList: false,
                    SVGStylable: false,
                    SVGStyleElement: false,
                    SVGSwitchElement: false,
                    SVGSymbolElement: false,
                    SVGTRefElement: false,
                    SVGTSpanElement: false,
                    SVGTests: false,
                    SVGTextContentElement: false,
                    SVGTextElement: false,
                    SVGTextPathElement: false,
                    SVGTextPositioningElement: false,
                    SVGTitleElement: false,
                    SVGTransform: false,
                    SVGTransformList: false,
                    SVGTransformable: false,
                    SVGURIReference: false,
                    SVGUnitTypes: false,
                    SVGUseElement: false,
                    SVGVKernElement: false,
                    SVGViewElement: false,
                    SVGViewSpec: false,
                    SVGZoomAndPan: false,
                    Text: false,
                    TextDecoder: false,
                    TextEncoder: false,
                    TimeEvent: false,
                    top: false,
                    URL: false,
                    WebGLActiveInfo: false,
                    WebGLBuffer: false,
                    WebGLContextEvent: false,
                    WebGLFramebuffer: false,
                    WebGLProgram: false,
                    WebGLRenderbuffer: false,
                    WebGLRenderingContext: false,
                    WebGLShader: false,
                    WebGLShaderPrecisionFormat: false,
                    WebGLTexture: false,
                    WebGLUniformLocation: false,
                    WebSocket: false,
                    window: false,
                    Window: false,
                    Worker: false,
                    XDomainRequest: false,
                    XMLHttpRequest: false,
                    XMLSerializer: false,
                    XPathEvaluator: false,
                    XPathException: false,
                    XPathExpression: false,
                    XPathNamespace: false,
                    XPathNSResolver: false,
                    XPathResult: false
                };

                exports.devel = {
                    alert: false,
                    confirm: false,
                    console: false,
                    Debug: false,
                    opera: false,
                    prompt: false
                };

                exports.worker = {
                    importScripts: true,
                    postMessage: true,
                    self: true,
                    FileReaderSync: true
                };
                exports.nonstandard = {
                    escape: false,
                    unescape: false
                };

                exports.couch = {
                    "require": false,
                    respond: false,
                    getRow: false,
                    emit: false,
                    send: false,
                    start: false,
                    sum: false,
                    log: false,
                    exports: false,
                    module: false,
                    provides: false
                };

                exports.node = {
                    __filename: false,
                    __dirname: false,
                    GLOBAL: false,
                    global: false,
                    module: false,
                    require: false,

                    Buffer: true,
                    console: true,
                    exports: true,
                    process: true,
                    setTimeout: true,
                    clearTimeout: true,
                    setInterval: true,
                    clearInterval: true,
                    setImmediate: true, // v0.9.1+
                    clearImmediate: true // v0.9.1+
                };

                exports.browserify = {
                    __filename: false,
                    __dirname: false,
                    global: false,
                    module: false,
                    require: false,
                    Buffer: true,
                    exports: true,
                    process: true
                };

                exports.phantom = {
                    phantom: true,
                    require: true,
                    WebPage: true,
                    console: true, // in examples, but undocumented
                    exports: true // v1.7+
                };

                exports.qunit = {
                    asyncTest: false,
                    deepEqual: false,
                    equal: false,
                    expect: false,
                    module: false,
                    notDeepEqual: false,
                    notEqual: false,
                    notPropEqual: false,
                    notStrictEqual: false,
                    ok: false,
                    propEqual: false,
                    QUnit: false,
                    raises: false,
                    start: false,
                    stop: false,
                    strictEqual: false,
                    test: false,
                    "throws": false
                };

                exports.rhino = {
                    defineClass: false,
                    deserialize: false,
                    gc: false,
                    help: false,
                    importClass: false,
                    importPackage: false,
                    "java": false,
                    load: false,
                    loadClass: false,
                    Packages: false,
                    print: false,
                    quit: false,
                    readFile: false,
                    readUrl: false,
                    runCommand: false,
                    seal: false,
                    serialize: false,
                    spawn: false,
                    sync: false,
                    toint32: false,
                    version: false
                };

                exports.shelljs = {
                    target: false,
                    echo: false,
                    exit: false,
                    cd: false,
                    pwd: false,
                    ls: false,
                    find: false,
                    cp: false,
                    rm: false,
                    mv: false,
                    mkdir: false,
                    test: false,
                    cat: false,
                    sed: false,
                    grep: false,
                    which: false,
                    dirs: false,
                    pushd: false,
                    popd: false,
                    env: false,
                    exec: false,
                    chmod: false,
                    config: false,
                    error: false,
                    tempdir: false
                };

                exports.typed = {
                    ArrayBuffer: false,
                    ArrayBufferView: false,
                    DataView: false,
                    Float32Array: false,
                    Float64Array: false,
                    Int16Array: false,
                    Int32Array: false,
                    Int8Array: false,
                    Uint16Array: false,
                    Uint32Array: false,
                    Uint8Array: false,
                    Uint8ClampedArray: false
                };

                exports.wsh = {
                    ActiveXObject: true,
                    Enumerator: true,
                    GetObject: true,
                    ScriptEngine: true,
                    ScriptEngineBuildVersion: true,
                    ScriptEngineMajorVersion: true,
                    ScriptEngineMinorVersion: true,
                    VBArray: true,
                    WSH: true,
                    WScript: true,
                    XDomainRequest: true
                };

                exports.dojo = {
                    dojo: false,
                    dijit: false,
                    dojox: false,
                    define: false,
                    "require": false
                };

                exports.jquery = {
                    "$": false,
                    jQuery: false
                };

                exports.mootools = {
                    "$": false,
                    "$$": false,
                    Asset: false,
                    Browser: false,
                    Chain: false,
                    Class: false,
                    Color: false,
                    Cookie: false,
                    Core: false,
                    Document: false,
                    DomReady: false,
                    DOMEvent: false,
                    DOMReady: false,
                    Drag: false,
                    Element: false,
                    Elements: false,
                    Event: false,
                    Events: false,
                    Fx: false,
                    Group: false,
                    Hash: false,
                    HtmlTable: false,
                    IFrame: false,
                    IframeShim: false,
                    InputValidator: false,
                    instanceOf: false,
                    Keyboard: false,
                    Locale: false,
                    Mask: false,
                    MooTools: false,
                    Native: false,
                    Options: false,
                    OverText: false,
                    Request: false,
                    Scroller: false,
                    Slick: false,
                    Slider: false,
                    Sortables: false,
                    Spinner: false,
                    Swiff: false,
                    Tips: false,
                    Type: false,
                    typeOf: false,
                    URI: false,
                    Window: false
                };

                exports.prototypejs = {
                    "$": false,
                    "$$": false,
                    "$A": false,
                    "$F": false,
                    "$H": false,
                    "$R": false,
                    "$break": false,
                    "$continue": false,
                    "$w": false,
                    Abstract: false,
                    Ajax: false,
                    Class: false,
                    Enumerable: false,
                    Element: false,
                    Event: false,
                    Field: false,
                    Form: false,
                    Hash: false,
                    Insertion: false,
                    ObjectRange: false,
                    PeriodicalExecuter: false,
                    Position: false,
                    Prototype: false,
                    Selector: false,
                    Template: false,
                    Toggle: false,
                    Try: false,
                    Autocompleter: false,
                    Builder: false,
                    Control: false,
                    Draggable: false,
                    Draggables: false,
                    Droppables: false,
                    Effect: false,
                    Sortable: false,
                    SortableObserver: false,
                    Sound: false,
                    Scriptaculous: false
                };

                exports.yui = {
                    YUI: false,
                    Y: false,
                    YUI_config: false
                };

                exports.mocha = {
                    mocha: false,
                    describe: false,
                    xdescribe: false,
                    it: false,
                    xit: false,
                    context: false,
                    xcontext: false,
                    before: false,
                    after: false,
                    beforeEach: false,
                    afterEach: false,
                    suite: false,
                    test: false,
                    setup: false,
                    teardown: false,
                    suiteSetup: false,
                    suiteTeardown: false
                };

                exports.jasmine = {
                    jasmine: false,
                    describe: false,
                    xdescribe: false,
                    it: false,
                    xit: false,
                    beforeEach: false,
                    afterEach: false,
                    setFixtures: false,
                    loadFixtures: false,
                    spyOn: false,
                    expect: false,
                    runs: false,
                    waitsFor: false,
                    waits: false,
                    beforeAll: false,
                    afterAll: false,
                    fail: false,
                    fdescribe: false,
                    fit: false,
                    pending: false
                };

            }, {}]
        }, {}, ["/node_modules/jshint/src/jshint.js"]);

});

define("ace/mode/javascript_worker", ["require", "exports", "module", "ace/lib/oop", "ace/worker/mirror", "ace/mode/javascript/jshint"], function(require, exports, module) {
    "use strict";

    var oop = require("../lib/oop");
    var Mirror = require("../worker/mirror").Mirror;
    var lint = require("./javascript/jshint").JSHINT;

    function startRegex(arr) {
        return RegExp("^(" + arr.join("|") + ")");
    }

    var disabledWarningsRe = startRegex([
        "Bad for in variable '(.+)'.",
        'Missing "use strict"'
    ]);
    var errorsRe = startRegex([
        "Unexpected",
        "Expected ",
        "Confusing (plus|minus)",
        "\\{a\\} unterminated regular expression",
        "Unclosed ",
        "Unmatched ",
        "Unbegun comment",
        "Bad invocation",
        "Missing space after",
        "Missing operator at"
    ]);
    var infoRe = startRegex([
        "Expected an assignment",
        "Bad escapement of EOL",
        "Unexpected comma",
        "Unexpected space",
        "Missing radix parameter.",
        "A leading decimal point can",
        "\\['{a}'\\] is better written in dot notation.",
        "'{a}' used out of scope"
    ]);

    var JavaScriptWorker = exports.JavaScriptWorker = function(sender) {
        Mirror.call(this, sender);
        this.setTimeout(500);
        this.setOptions();
    };

    oop.inherits(JavaScriptWorker, Mirror);

    (function() {
        this.setOptions = function(options) {
            this.options = options || {
                esnext: true,
                moz: true,
                devel: true,
                browser: true,
                node: true,
                laxcomma: true,
                laxbreak: true,
                lastsemic: true,
                onevar: false,
                passfail: false,
                maxerr: 100,
                expr: true,
                multistr: true,
                globalstrict: true
            };
            this.doc.getValue() && this.deferredUpdate.schedule(100);
        };

        this.changeOptions = function(newOptions) {
            oop.mixin(this.options, newOptions);
            this.doc.getValue() && this.deferredUpdate.schedule(100);
        };

        this.isValidJS = function(str) {
            try {
                eval("throw 0;" + str);
            } catch (e) {
                if (e === 0)
                    return true;
            }
            return false
        };

        this.onUpdate = function() {
            var value = this.doc.getValue();
            value = value.replace(/^#!.*\n/, "\n");
            if (!value)
                return this.sender.emit("annotate", []);

            var errors = [];
            var maxErrorLevel = this.isValidJS(value) ? "warning" : "error";
            lint(value, this.options, this.options.globals);
            var results = lint.errors;

            var errorAdded = false
            for (var i = 0; i < results.length; i++) {
                var error = results[i];
                if (!error)
                    continue;
                var raw = error.raw;
                var type = "warning";

                if (raw == "Missing semicolon.") {
                    var str = error.evidence.substr(error.character);
                    str = str.charAt(str.search(/\S/));
                    if (maxErrorLevel == "error" && str && /[\w\d{(['"]/.test(str)) {
                        error.reason = 'Missing ";" before statement';
                        type = "error";
                    } else {
                        type = "info";
                    }
                } else if (disabledWarningsRe.test(raw)) {
                    continue;
                } else if (infoRe.test(raw)) {
                    type = "info"
                } else if (errorsRe.test(raw)) {
                    errorAdded = true;
                    type = maxErrorLevel;
                } else if (raw == "'{a}' is not defined.") {
                    type = "warning";
                } else if (raw == "'{a}' is defined but never used.") {
                    type = "info";
                }

                errors.push({
                    row: error.line - 1,
                    column: error.character - 1,
                    text: error.reason,
                    type: type,
                    raw: raw
                });

                if (errorAdded) {}
            }

            this.sender.emit("annotate", errors);
        };

    }).call(JavaScriptWorker.prototype);

});

define("ace/lib/es5-shim", ["require", "exports", "module"], function(require, exports, module) {

    function Empty() {}

    if (!Function.prototype.bind) {
        Function.prototype.bind = function bind(that) { // .length is 1
            var target = this;
            if (typeof target != "function") {
                throw new TypeError("Function.prototype.bind called on incompatible " + target);
            }
            var args = slice.call(arguments, 1); // for normal call
            var bound = function() {

                if (this instanceof bound) {

                    var result = target.apply(
                        this,
                        args.concat(slice.call(arguments))
                    );
                    if (Object(result) === result) {
                        return result;
                    }
                    return this;

                } else {
                    return target.apply(
                        that,
                        args.concat(slice.call(arguments))
                    );

                }

            };
            if (target.prototype) {
                Empty.prototype = target.prototype;
                bound.prototype = new Empty();
                Empty.prototype = null;
            }
            return bound;
        };
    }
    var call = Function.prototype.call;
    var prototypeOfArray = Array.prototype;
    var prototypeOfObject = Object.prototype;
    var slice = prototypeOfArray.slice;
    var _toString = call.bind(prototypeOfObject.toString);
    var owns = call.bind(prototypeOfObject.hasOwnProperty);
    var defineGetter;
    var defineSetter;
    var lookupGetter;
    var lookupSetter;
    var supportsAccessors;
    if ((supportsAccessors = owns(prototypeOfObject, "__defineGetter__"))) {
        defineGetter = call.bind(prototypeOfObject.__defineGetter__);
        defineSetter = call.bind(prototypeOfObject.__defineSetter__);
        lookupGetter = call.bind(prototypeOfObject.__lookupGetter__);
        lookupSetter = call.bind(prototypeOfObject.__lookupSetter__);
    }
    if ([1, 2].splice(0).length != 2) {
        if (function() { // test IE < 9 to splice bug - see issue #138
                function makeArray(l) {
                    var a = new Array(l + 2);
                    a[0] = a[1] = 0;
                    return a;
                }
                var array = [],
                    lengthBefore;

                array.splice.apply(array, makeArray(20));
                array.splice.apply(array, makeArray(26));

                lengthBefore = array.length; //46
                array.splice(5, 0, "XXX"); // add one element

                lengthBefore + 1 == array.length

                if (lengthBefore + 1 == array.length) {
                    return true; // has right splice implementation without bugs
                }
            }()) { //IE 6/7
            var array_splice = Array.prototype.splice;
            Array.prototype.splice = function(start, deleteCount) {
                if (!arguments.length) {
                    return [];
                } else {
                    return array_splice.apply(this, [
                        start === void 0 ? 0 : start,
                        deleteCount === void 0 ? (this.length - start) : deleteCount
                    ].concat(slice.call(arguments, 2)))
                }
            };
        } else { //IE8
            Array.prototype.splice = function(pos, removeCount) {
                var length = this.length;
                if (pos > 0) {
                    if (pos > length)
                        pos = length;
                } else if (pos == void 0) {
                    pos = 0;
                } else if (pos < 0) {
                    pos = Math.max(length + pos, 0);
                }

                if (!(pos + removeCount < length))
                    removeCount = length - pos;

                var removed = this.slice(pos, pos + removeCount);
                var insert = slice.call(arguments, 2);
                var add = insert.length;
                if (pos === length) {
                    if (add) {
                        this.push.apply(this, insert);
                    }
                } else {
                    var remove = Math.min(removeCount, length - pos);
                    var tailOldPos = pos + remove;
                    var tailNewPos = tailOldPos + add - remove;
                    var tailCount = length - tailOldPos;
                    var lengthAfterRemove = length - remove;

                    if (tailNewPos < tailOldPos) { // case A
                        for (var i = 0; i < tailCount; ++i) {
                            this[tailNewPos + i] = this[tailOldPos + i];
                        }
                    } else if (tailNewPos > tailOldPos) { // case B
                        for (i = tailCount; i--;) {
                            this[tailNewPos + i] = this[tailOldPos + i];
                        }
                    } // else, add == remove (nothing to do)

                    if (add && pos === lengthAfterRemove) {
                        this.length = lengthAfterRemove; // truncate array
                        this.push.apply(this, insert);
                    } else {
                        this.length = lengthAfterRemove + add; // reserves space
                        for (i = 0; i < add; ++i) {
                            this[pos + i] = insert[i];
                        }
                    }
                }
                return removed;
            };
        }
    }
    if (!Array.isArray) {
        Array.isArray = function isArray(obj) {
            return _toString(obj) == "[object Array]";
        };
    }
    var boxedString = Object("a"),
        splitString = boxedString[0] != "a" || !(0 in boxedString);

    if (!Array.prototype.forEach) {
        Array.prototype.forEach = function forEach(fun /*, thisp*/ ) {
            var object = toObject(this),
                self = splitString && _toString(this) == "[object String]" ?
                this.split("") :
                object,
                thisp = arguments[1],
                i = -1,
                length = self.length >>> 0;
            if (_toString(fun) != "[object Function]") {
                throw new TypeError(); // TODO message
            }

            while (++i < length) {
                if (i in self) {
                    fun.call(thisp, self[i], i, object);
                }
            }
        };
    }
    if (!Array.prototype.map) {
        Array.prototype.map = function map(fun /*, thisp*/ ) {
            var object = toObject(this),
                self = splitString && _toString(this) == "[object String]" ?
                this.split("") :
                object,
                length = self.length >>> 0,
                result = Array(length),
                thisp = arguments[1];
            if (_toString(fun) != "[object Function]") {
                throw new TypeError(fun + " is not a function");
            }

            for (var i = 0; i < length; i++) {
                if (i in self)
                    result[i] = fun.call(thisp, self[i], i, object);
            }
            return result;
        };
    }
    if (!Array.prototype.filter) {
        Array.prototype.filter = function filter(fun /*, thisp */ ) {
            var object = toObject(this),
                self = splitString && _toString(this) == "[object String]" ?
                this.split("") :
                object,
                length = self.length >>> 0,
                result = [],
                value,
                thisp = arguments[1];
            if (_toString(fun) != "[object Function]") {
                throw new TypeError(fun + " is not a function");
            }

            for (var i = 0; i < length; i++) {
                if (i in self) {
                    value = self[i];
                    if (fun.call(thisp, value, i, object)) {
                        result.push(value);
                    }
                }
            }
            return result;
        };
    }
    if (!Array.prototype.every) {
        Array.prototype.every = function every(fun /*, thisp */ ) {
            var object = toObject(this),
                self = splitString && _toString(this) == "[object String]" ?
                this.split("") :
                object,
                length = self.length >>> 0,
                thisp = arguments[1];
            if (_toString(fun) != "[object Function]") {
                throw new TypeError(fun + " is not a function");
            }

            for (var i = 0; i < length; i++) {
                if (i in self && !fun.call(thisp, self[i], i, object)) {
                    return false;
                }
            }
            return true;
        };
    }
    if (!Array.prototype.some) {
        Array.prototype.some = function some(fun /*, thisp */ ) {
            var object = toObject(this),
                self = splitString && _toString(this) == "[object String]" ?
                this.split("") :
                object,
                length = self.length >>> 0,
                thisp = arguments[1];
            if (_toString(fun) != "[object Function]") {
                throw new TypeError(fun + " is not a function");
            }

            for (var i = 0; i < length; i++) {
                if (i in self && fun.call(thisp, self[i], i, object)) {
                    return true;
                }
            }
            return false;
        };
    }
    if (!Array.prototype.reduce) {
        Array.prototype.reduce = function reduce(fun /*, initial*/ ) {
            var object = toObject(this),
                self = splitString && _toString(this) == "[object String]" ?
                this.split("") :
                object,
                length = self.length >>> 0;
            if (_toString(fun) != "[object Function]") {
                throw new TypeError(fun + " is not a function");
            }
            if (!length && arguments.length == 1) {
                throw new TypeError("reduce of empty array with no initial value");
            }

            var i = 0;
            var result;
            if (arguments.length >= 2) {
                result = arguments[1];
            } else {
                do {
                    if (i in self) {
                        result = self[i++];
                        break;
                    }
                    if (++i >= length) {
                        throw new TypeError("reduce of empty array with no initial value");
                    }
                } while (true);
            }

            for (; i < length; i++) {
                if (i in self) {
                    result = fun.call(void 0, result, self[i], i, object);
                }
            }

            return result;
        };
    }
    if (!Array.prototype.reduceRight) {
        Array.prototype.reduceRight = function reduceRight(fun /*, initial*/ ) {
            var object = toObject(this),
                self = splitString && _toString(this) == "[object String]" ?
                this.split("") :
                object,
                length = self.length >>> 0;
            if (_toString(fun) != "[object Function]") {
                throw new TypeError(fun + " is not a function");
            }
            if (!length && arguments.length == 1) {
                throw new TypeError("reduceRight of empty array with no initial value");
            }

            var result, i = length - 1;
            if (arguments.length >= 2) {
                result = arguments[1];
            } else {
                do {
                    if (i in self) {
                        result = self[i--];
                        break;
                    }
                    if (--i < 0) {
                        throw new TypeError("reduceRight of empty array with no initial value");
                    }
                } while (true);
            }

            do {
                if (i in this) {
                    result = fun.call(void 0, result, self[i], i, object);
                }
            } while (i--);

            return result;
        };
    }
    if (!Array.prototype.indexOf || ([0, 1].indexOf(1, 2) != -1)) {
        Array.prototype.indexOf = function indexOf(sought /*, fromIndex */ ) {
            var self = splitString && _toString(this) == "[object String]" ?
                this.split("") :
                toObject(this),
                length = self.length >>> 0;

            if (!length) {
                return -1;
            }

            var i = 0;
            if (arguments.length > 1) {
                i = toInteger(arguments[1]);
            }
            i = i >= 0 ? i : Math.max(0, length + i);
            for (; i < length; i++) {
                if (i in self && self[i] === sought) {
                    return i;
                }
            }
            return -1;
        };
    }
    if (!Array.prototype.lastIndexOf || ([0, 1].lastIndexOf(0, -3) != -1)) {
        Array.prototype.lastIndexOf = function lastIndexOf(sought /*, fromIndex */ ) {
            var self = splitString && _toString(this) == "[object String]" ?
                this.split("") :
                toObject(this),
                length = self.length >>> 0;

            if (!length) {
                return -1;
            }
            var i = length - 1;
            if (arguments.length > 1) {
                i = Math.min(i, toInteger(arguments[1]));
            }
            i = i >= 0 ? i : length - Math.abs(i);
            for (; i >= 0; i--) {
                if (i in self && sought === self[i]) {
                    return i;
                }
            }
            return -1;
        };
    }
    if (!Object.getPrototypeOf) {
        Object.getPrototypeOf = function getPrototypeOf(object) {
            return object.__proto__ || (
                object.constructor ?
                object.constructor.prototype :
                prototypeOfObject
            );
        };
    }
    if (!Object.getOwnPropertyDescriptor) {
        var ERR_NON_OBJECT = "Object.getOwnPropertyDescriptor called on a " +
            "non-object: ";
        Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) {
            if ((typeof object != "object" && typeof object != "function") || object === null)
                throw new TypeError(ERR_NON_OBJECT + object);
            if (!owns(object, property))
                return;

            var descriptor, getter, setter;
            descriptor = {
                enumerable: true,
                configurable: true
            };
            if (supportsAccessors) {
                var prototype = object.__proto__;
                object.__proto__ = prototypeOfObject;

                var getter = lookupGetter(object, property);
                var setter = lookupSetter(object, property);
                object.__proto__ = prototype;

                if (getter || setter) {
                    if (getter) descriptor.get = getter;
                    if (setter) descriptor.set = setter;
                    return descriptor;
                }
            }
            descriptor.value = object[property];
            return descriptor;
        };
    }
    if (!Object.getOwnPropertyNames) {
        Object.getOwnPropertyNames = function getOwnPropertyNames(object) {
            return Object.keys(object);
        };
    }
    if (!Object.create) {
        var createEmpty;
        if (Object.prototype.__proto__ === null) {
            createEmpty = function() {
                return {
                    "__proto__": null
                };
            };
        } else {
            createEmpty = function() {
                var empty = {};
                for (var i in empty)
                    empty[i] = null;
                empty.constructor =
                    empty.hasOwnProperty =
                    empty.propertyIsEnumerable =
                    empty.isPrototypeOf =
                    empty.toLocaleString =
                    empty.toString =
                    empty.valueOf =
                    empty.__proto__ = null;
                return empty;
            }
        }

        Object.create = function create(prototype, properties) {
            var object;
            if (prototype === null) {
                object = createEmpty();
            } else {
                if (typeof prototype != "object")
                    throw new TypeError("typeof prototype[" + (typeof prototype) + "] != 'object'");
                var Type = function() {};
                Type.prototype = prototype;
                object = new Type();
                object.__proto__ = prototype;
            }
            if (properties !== void 0)
                Object.defineProperties(object, properties);
            return object;
        };
    }

    function doesDefinePropertyWork(object) {
        try {
            Object.defineProperty(object, "sentinel", {});
            return "sentinel" in object;
        } catch (exception) {}
    }
    if (Object.defineProperty) {
        var definePropertyWorksOnObject = doesDefinePropertyWork({});
        var definePropertyWorksOnDom = typeof document == "undefined" ||
            doesDefinePropertyWork(document.createElement("div"));
        if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) {
            var definePropertyFallback = Object.defineProperty;
        }
    }

    if (!Object.defineProperty || definePropertyFallback) {
        var ERR_NON_OBJECT_DESCRIPTOR = "Property description must be an object: ";
        var ERR_NON_OBJECT_TARGET = "Object.defineProperty called on non-object: "
        var ERR_ACCESSORS_NOT_SUPPORTED = "getters & setters can not be defined " +
            "on this javascript engine";

        Object.defineProperty = function defineProperty(object, property, descriptor) {
            if ((typeof object != "object" && typeof object != "function") || object === null)
                throw new TypeError(ERR_NON_OBJECT_TARGET + object);
            if ((typeof descriptor != "object" && typeof descriptor != "function") || descriptor === null)
                throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor);
            if (definePropertyFallback) {
                try {
                    return definePropertyFallback.call(Object, object, property, descriptor);
                } catch (exception) {}
            }
            if (owns(descriptor, "value")) {

                if (supportsAccessors && (lookupGetter(object, property) ||
                        lookupSetter(object, property))) {
                    var prototype = object.__proto__;
                    object.__proto__ = prototypeOfObject;
                    delete object[property];
                    object[property] = descriptor.value;
                    object.__proto__ = prototype;
                } else {
                    object[property] = descriptor.value;
                }
            } else {
                if (!supportsAccessors)
                    throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);
                if (owns(descriptor, "get"))
                    defineGetter(object, property, descriptor.get);
                if (owns(descriptor, "set"))
                    defineSetter(object, property, descriptor.set);
            }

            return object;
        };
    }
    if (!Object.defineProperties) {
        Object.defineProperties = function defineProperties(object, properties) {
            for (var property in properties) {
                if (owns(properties, property))
                    Object.defineProperty(object, property, properties[property]);
            }
            return object;
        };
    }
    if (!Object.seal) {
        Object.seal = function seal(object) {
            return object;
        };
    }
    if (!Object.freeze) {
        Object.freeze = function freeze(object) {
            return object;
        };
    }
    try {
        Object.freeze(function() {});
    } catch (exception) {
        Object.freeze = (function freeze(freezeObject) {
            return function freeze(object) {
                if (typeof object == "function") {
                    return object;
                } else {
                    return freezeObject(object);
                }
            };
        })(Object.freeze);
    }
    if (!Object.preventExtensions) {
        Object.preventExtensions = function preventExtensions(object) {
            return object;
        };
    }
    if (!Object.isSealed) {
        Object.isSealed = function isSealed(object) {
            return false;
        };
    }
    if (!Object.isFrozen) {
        Object.isFrozen = function isFrozen(object) {
            return false;
        };
    }
    if (!Object.isExtensible) {
        Object.isExtensible = function isExtensible(object) {
            if (Object(object) === object) {
                throw new TypeError(); // TODO message
            }
            var name = '';
            while (owns(object, name)) {
                name += '?';
            }
            object[name] = true;
            var returnValue = owns(object, name);
            delete object[name];
            return returnValue;
        };
    }
    if (!Object.keys) {
        var hasDontEnumBug = true,
            dontEnums = [
                "toString",
                "toLocaleString",
                "valueOf",
                "hasOwnProperty",
                "isPrototypeOf",
                "propertyIsEnumerable",
                "constructor"
            ],
            dontEnumsLength = dontEnums.length;

        for (var key in {
                "toString": null
            }) {
            hasDontEnumBug = false;
        }

        Object.keys = function keys(object) {

            if (
                (typeof object != "object" && typeof object != "function") ||
                object === null
            ) {
                throw new TypeError("Object.keys called on a non-object");
            }

            var keys = [];
            for (var name in object) {
                if (owns(object, name)) {
                    keys.push(name);
                }
            }

            if (hasDontEnumBug) {
                for (var i = 0, ii = dontEnumsLength; i < ii; i++) {
                    var dontEnum = dontEnums[i];
                    if (owns(object, dontEnum)) {
                        keys.push(dontEnum);
                    }
                }
            }
            return keys;
        };

    }
    if (!Date.now) {
        Date.now = function now() {
            return new Date().getTime();
        };
    }
    var ws = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003" +
        "\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028" +
        "\u2029\uFEFF";
    if (!String.prototype.trim || ws.trim()) {
        ws = "[" + ws + "]";
        var trimBeginRegexp = new RegExp("^" + ws + ws + "*"),
            trimEndRegexp = new RegExp(ws + ws + "*$");
        String.prototype.trim = function trim() {
            return String(this).replace(trimBeginRegexp, "").replace(trimEndRegexp, "");
        };
    }

    function toInteger(n) {
        n = +n;
        if (n !== n) { // isNaN
            n = 0;
        } else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) {
            n = (n > 0 || -1) * Math.floor(Math.abs(n));
        }
        return n;
    }

    function isPrimitive(input) {
        var type = typeof input;
        return (
            input === null ||
            type === "undefined" ||
            type === "boolean" ||
            type === "number" ||
            type === "string"
        );
    }

    function toPrimitive(input) {
        var val, valueOf, toString;
        if (isPrimitive(input)) {
            return input;
        }
        valueOf = input.valueOf;
        if (typeof valueOf === "function") {
            val = valueOf.call(input);
            if (isPrimitive(val)) {
                return val;
            }
        }
        toString = input.toString;
        if (typeof toString === "function") {
            val = toString.call(input);
            if (isPrimitive(val)) {
                return val;
            }
        }
        throw new TypeError();
    }
    var toObject = function(o) {
        if (o == null) { // this matches both null and undefined
            throw new TypeError("can't convert " + o + " to object");
        }
        return Object(o);
    };

});
